Updating websocket++ to latest github release (0.3 alpha4).

This commit is contained in:
lotodore
2013-10-11 23:54:30 +02:00
parent 2d6db51465
commit 0368b57432
23 changed files with 732 additions and 627 deletions
+122
View File
@@ -1,3 +1,5 @@
Main Library:
Copyright (c) 2013, Peter Thorson. All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -21,3 +23,123 @@ 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.
Bundled Libraries:
****** Base 64 Library (base64/base64.hpp) ******
base64.hpp is a repackaging of the base64.cpp and base64.h files into a
single header suitable for use as a header only library. This conversion was
done by Peter Thorson (webmaster@zaphoyd.com) in 2012. All modifications to
the code are redistributed under the same license as the original, which is
listed below.
base64.cpp and base64.h
Copyright (C) 2004-2008 René Nyffenegger
This source code is provided 'as-is', without any express or implied
warranty. In no event will the author be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this source code must not be misrepresented; you must not
claim that you wrote the original source code. If you use this source code
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original source code.
3. This notice may not be removed or altered from any source distribution.
René Nyffenegger rene.nyffenegger@adp-gmbh.ch
****** SHA1 Library (sha1/sha1.hpp) ******
sha1.hpp is a repackaging of the sha1.cpp and sha1.h files from the shallsha1
library (http://code.google.com/p/smallsha1/) into a single header suitable for
use as a header only library. This conversion was done by Peter Thorson
(webmaster@zaphoyd.com) in 2013. All modifications to the code are redistributed
under the same license as the original, which is listed below.
Copyright (c) 2011, Micael Hildenborg
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 Micael Hildenborg 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 Micael Hildenborg ''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 Micael Hildenborg 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.
****** MD5 Library (common/md5.hpp) ******
md5.hpp is a reformulation of the md5.h and md5.c code from
http://www.opensource.apple.com/source/cups/cups-59/cups/md5.c to allow it to
function as a component of a header only library. This conversion was done by
Peter Thorson (webmaster@zaphoyd.com) in 2012 for the WebSocket++ project. The
changes are released under the same license as the original (listed below)
Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved.
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
L. Peter Deutsch
ghost@aladdin.com
****** UTF8 Validation logic (utf8_validation.hpp) ******
utf8_validation.hpp is adapted from code originally written by Bjoern Hoehrmann
<bjoern@hoehrmann.de>. See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for
details.
The original license:
Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+1 -1
View File
@@ -1,7 +1,7 @@
/*
******
base64.hpp is a repackaging of the base64.cpp and base64.h files into a
single headersuitable for use as a header only library. This conversion was
single header suitable for use as a header only library. This conversion was
done by Peter Thorson (webmaster@zaphoyd.com) in 2012. All modifications to
the code are redistributed under the same license as the original, which is
listed below.
+4 -3
View File
@@ -1,7 +1,8 @@
/*
md5.hpp is a reformulation of the md5.h and md5.c code to allow it to function
as a component of a header only library. This conversion was done by Peter
Thorson (webmaster@zaphoyd.com) in 2012 for the WebSocket++ project. The
md5.hpp is a reformulation of the md5.h and md5.c code from
http://www.opensource.apple.com/source/cups/cups-59/cups/md5.c to allow it to
function as a component of a header only library. This conversion was done by
Peter Thorson (webmaster@zaphoyd.com) in 2012 for the WebSocket++ project. The
changes are released under the same license as the original (listed below)
*/
/*
+7 -4
View File
@@ -229,30 +229,37 @@ public:
m_close_handler = h;
}
void set_fail_handler(fail_handler h) {
m_alog.write(log::alevel::devel,"set_fail_handler");
scoped_lock_type guard(m_mutex);
m_fail_handler = h;
}
void set_ping_handler(ping_handler h) {
m_alog.write(log::alevel::devel,"set_ping_handler");
scoped_lock_type guard(m_mutex);
m_ping_handler = h;
}
void set_pong_handler(pong_handler h) {
m_alog.write(log::alevel::devel,"set_pong_handler");
scoped_lock_type guard(m_mutex);
m_pong_handler = h;
}
void set_pong_timeout_handler(pong_timeout_handler h) {
m_alog.write(log::alevel::devel,"set_pong_timeout_handler");
scoped_lock_type guard(m_mutex);
m_pong_timeout_handler = h;
}
void set_interrupt_handler(interrupt_handler h) {
m_alog.write(log::alevel::devel,"set_interrupt_handler");
scoped_lock_type guard(m_mutex);
m_interrupt_handler = h;
}
void set_http_handler(http_handler h) {
m_alog.write(log::alevel::devel,"set_http_handler");
scoped_lock_type guard(m_mutex);
m_http_handler = h;
}
void set_validate_handler(validate_handler h) {
m_alog.write(log::alevel::devel,"set_validate_handler");
scoped_lock_type guard(m_mutex);
m_validate_handler = h;
}
@@ -390,7 +397,6 @@ public:
}
protected:
connection_ptr create_connection();
void remove_connection(connection_ptr con);
alog_type m_alog;
elog_type m_elog;
@@ -411,9 +417,6 @@ private:
rng_type m_rng;
// endpoint resources
std::set<connection_ptr> m_connections;
// static settings
bool const m_is_server;
@@ -1177,27 +1177,27 @@ void connection<config>::handle_send_http_response(
this->log_open_result();
if (m_handshake_timer) {
m_handshake_timer->cancel();
m_handshake_timer.reset();
}
if (m_response.get_status_code() != http::status_code::switching_protocols)
{
if (m_processor) {
// if this was not a websocket connection, we have written
// the expected response and the connection can be closed.
} else {
// this was a websocket connection that ended in an error
std::stringstream s;
s << "Handshake ended with HTTP error: "
<< m_response.get_status_code();
m_elog.write(log::elevel::rerror,s.str());
} else {
// if this was not a websocket connection, we have written
// the expected response and the connection can be closed.
}
this->terminate(make_error_code(error::http_connection_ended));
return;
}
if (m_handshake_timer) {
m_handshake_timer->cancel();
m_handshake_timer.reset();
}
this->atomic_state_change(
istate::PROCESS_HTTP_REQUEST,
istate::PROCESS_CONNECTION,
@@ -1339,6 +1339,11 @@ void connection<config>::handle_read_http_response(const lib::error_code& ec,
m_alog.write(log::alevel::devel,std::string("Raw response: ")+m_response.raw());
if (m_response.headers_ready()) {
if (m_handshake_timer) {
m_handshake_timer->cancel();
m_handshake_timer.reset();
}
lib::error_code ec = m_processor->validate_server_handshake_response(
m_request,
m_response
@@ -1361,11 +1366,6 @@ void connection<config>::handle_read_http_response(const lib::error_code& ec,
"handle_read_http_response must be called from READ_HTTP_RESPONSE state"
);
if (m_handshake_timer) {
m_handshake_timer->cancel();
m_handshake_timer.reset();
}
this->log_open_result();
if (m_open_handler) {
@@ -50,9 +50,6 @@ endpoint<connection,config>::create_connection() {
// Cast that weak pointer to void* and manage it using another shared_ptr
// connection_hdl hdl(reinterpret_cast<void*>(new connection_weak_ptr(con)));
// con->set_handle(hdl);
//
con->set_handle(w);
// Copy default handlers from the endpoint
@@ -67,14 +64,6 @@ endpoint<connection,config>::create_connection() {
con->set_validate_handler(m_validate_handler);
con->set_message_handler(m_message_handler);
con->set_termination_handler(
lib::bind(
&type::remove_connection,
this,
lib::placeholders::_1
)
);
lib::error_code ec;
ec = transport_type::init(con);
@@ -83,9 +72,6 @@ endpoint<connection,config>::create_connection() {
return connection_ptr();
}
scoped_lock_type lock(m_mutex);
m_connections.insert(con);
return con;
}
@@ -216,20 +202,6 @@ void endpoint<connection,config>::pong(connection_hdl hdl, std::string const &
if (ec) { throw ec; }
}
template <typename connection, typename config>
void endpoint<connection,config>::remove_connection(connection_ptr con) {
std::stringstream s;
s << "remove_connection. New count: " << m_connections.size()-1;
m_alog.write(log::alevel::devel,s.str());
scoped_lock_type lock(m_mutex);
// unregister the termination handler
con->set_termination_handler(termination_handler());
m_connections.erase(con);
}
} // namespace websocketpp
#endif // WEBSOCKETPP_ENDPOINT_IMPL_HPP
@@ -614,27 +614,11 @@ protected:
lib::error_code process_handshake_key(std::string & key) const {
key.append(constants::handshake_guid);
sha1 sha;
uint32_t message_digest[5];
unsigned char message_digest[20];
sha1::calc(key.c_str(),key.length(),message_digest);
key = base64_encode(message_digest,20);
sha << key.c_str();
if (sha.get_raw_digest(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]);
}
key = base64_encode(
reinterpret_cast<unsigned char const *>(message_digest),
20
);
return lib::error_code();
} else {
return error::make_error_code(error::sha1_library);
}
return lib::error_code();
}
/// Reads bytes from buf into m_basic_header
@@ -66,8 +66,7 @@ public:
explicit client() : endpoint_type(false)
{
endpoint_type::m_alog.write(log::alevel::devel,
"client constructor");
endpoint_type::m_alog.write(log::alevel::devel, "client constructor");
}
/// Get a new connection
@@ -77,15 +76,17 @@ public:
* applying connection specific settings before performing the opening
* handshake.
*
* @param [in] location URI to open the connection to as a uri_ptr
* @param [out] ec An status code indicating failure reasons, if any
*
* @return A connection_ptr to the new connection
*/
connection_ptr get_connection(uri_ptr location, lib::error_code &ec) {
connection_ptr get_connection(uri_ptr location, lib::error_code & ec) {
if (location->get_secure() && !transport_type::is_secure()) {
ec = error::make_error_code(error::endpoint_not_secure);
return connection_ptr();
}
// create connection
connection_ptr con = endpoint_type::create_connection();
if (!con) {
@@ -95,7 +96,6 @@ public:
con->set_uri(location);
// Success
ec = lib::error_code();
return con;
}
@@ -106,10 +106,12 @@ public:
* suitable for passing to connect(connection_ptr). This overload allows
* default construction of the uri_ptr from a standard string.
*
* @param [in] u URI to open the connection to as a string
* @param [out] ec An status code indicating failure reasons, if any
*
* @return A connection_ptr to the new connection
*/
connection_ptr get_connection(const std::string& u, lib::error_code &ec) {
// parse uri
connection_ptr get_connection(std::string const & u, lib::error_code & ec) {
uri_ptr location(new uri(u));
if (!location->get_valid()) {
@@ -137,35 +139,17 @@ public:
lib::bind(
&type::handle_connect,
this,
lib::placeholders::_1,
lib::placeholders::_2
con,
lib::placeholders::_1
)
);
return con;
}
// connect(...)
private:
// handle_connect
void handle_connect(connection_hdl hdl, const lib::error_code & ec) {
lib::error_code hdl_ec;
connection_ptr con = endpoint_type::get_con_from_hdl(hdl,hdl_ec);
if (hdl_ec == error::bad_connection) {
endpoint_type::m_elog.write(log::elevel::fatal,
"handle_connect got an invalid handle back");
} else if (hdl_ec) {
// There was some other unknown error attempting to convert the hdl
// to a connection.
endpoint_type::m_elog.write(log::elevel::fatal,
"handle_connect error in get_con_from_hdl: "+hdl_ec.message());
//con->terminate();
} else if (ec) {
// TODO
// Set connection's failure reasons
void handle_connect(connection_ptr con, lib::error_code const & ec) {
if (ec) {
con->terminate(ec);
endpoint_type::m_elog.write(log::elevel::rerror,
@@ -90,37 +90,20 @@ public:
lib::bind(
&type::handle_accept,
this,
lib::placeholders::_1,
lib::placeholders::_2
con,
lib::placeholders::_1
)
);
}
void handle_accept(connection_hdl hdl, const lib::error_code& ec) {
lib::error_code hdl_ec;
connection_ptr con = endpoint_type::get_con_from_hdl(hdl,hdl_ec);
void handle_accept(connection_ptr con, const lib::error_code& ec) {
if (ec) {
con->terminate(ec);
if (hdl_ec == error::bad_connection) {
// The connection we were trying to connect went out of scope
// This really shouldn't happen
endpoint_type::m_elog.write(log::elevel::fatal,
"handle_accept got an invalid handle back");
//con->terminate();
} else if (hdl_ec) {
// There was some other unknown error attempting to convert the hdl
// to a connection.
endpoint_type::m_elog.write(log::elevel::fatal,
"handle_accept error in get_con_from_hdl: "+hdl_ec.message());
//con->terminate();
endpoint_type::m_elog.write(log::elevel::rerror,
"handle_accept error: "+ec.message());
} else {
if (ec) {
con->terminate(ec);
endpoint_type::m_elog.write(log::elevel::rerror,
"handle_accept error: "+ec.message());
} else {
con->start();
}
con->start();
}
// TODO: are there cases where we should terminate this loop?
@@ -1,14 +0,0 @@
Copyright (C) 1998, 2009
Paul E. Jones <paulej@packetizer.com>
Freeware Public License (FPL)
This software is licensed as "freeware." Permission to distribute
this software in source and binary forms, including incorporation
into other products, is hereby granted without a fee. THIS SOFTWARE
IS PROVIDED 'AS IS' AND WITHOUT ANY EXPRESSED OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHOR SHALL NOT BE HELD
LIABLE FOR ANY DAMAGES RESULTING FROM THE USE OF THIS SOFTWARE, EITHER
DIRECTLY OR INDIRECTLY, INCLUDING, BUT NOT LIMITED TO, LOSS OF DATA
OR DATA BEING RENDERED INACCURATE.
+185
View File
@@ -0,0 +1,185 @@
/*
Copyright (c) 2011, Micael Hildenborg
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 Micael Hildenborg 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 Micael Hildenborg ''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 Micael Hildenborg 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.
*/
/*
Contributors:
Gustav
Several members in the gamedev.se forum.
Gregory Petrosyan
*/
#include "sha1.h"
namespace sha1
{
namespace // local
{
// Rotate an integer value to left.
inline const unsigned int rol(const unsigned int value,
const unsigned int steps)
{
return ((value << steps) | (value >> (32 - steps)));
}
// Sets the first 16 integers in the buffert to zero.
// Used for clearing the W buffert.
inline void clearWBuffert(unsigned int* buffert)
{
for (int pos = 16; --pos >= 0;)
{
buffert[pos] = 0;
}
}
void innerHash(unsigned int* result, unsigned int* w)
{
unsigned int a = result[0];
unsigned int b = result[1];
unsigned int c = result[2];
unsigned int d = result[3];
unsigned int e = result[4];
int round = 0;
#define sha1macro(func,val) \
{ \
const unsigned int t = rol(a, 5) + (func) + e + val + w[round]; \
e = d; \
d = c; \
c = rol(b, 30); \
b = a; \
a = t; \
}
while (round < 16)
{
sha1macro((b & c) | (~b & d), 0x5a827999)
++round;
}
while (round < 20)
{
w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1);
sha1macro((b & c) | (~b & d), 0x5a827999)
++round;
}
while (round < 40)
{
w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1);
sha1macro(b ^ c ^ d, 0x6ed9eba1)
++round;
}
while (round < 60)
{
w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1);
sha1macro((b & c) | (b & d) | (c & d), 0x8f1bbcdc)
++round;
}
while (round < 80)
{
w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1);
sha1macro(b ^ c ^ d, 0xca62c1d6)
++round;
}
#undef sha1macro
result[0] += a;
result[1] += b;
result[2] += c;
result[3] += d;
result[4] += e;
}
} // namespace
void calc(const void* src, const int bytelength, unsigned char* hash)
{
// Init the result array.
unsigned int result[5] = { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 };
// Cast the void src pointer to be the byte array we can work with.
const unsigned char* sarray = (const unsigned char*) src;
// The reusable round buffer
unsigned int w[80];
// Loop through all complete 64byte blocks.
const int endOfFullBlocks = bytelength - 64;
int endCurrentBlock;
int currentBlock = 0;
while (currentBlock <= endOfFullBlocks)
{
endCurrentBlock = currentBlock + 64;
// Init the round buffer with the 64 byte block data.
for (int roundPos = 0; currentBlock < endCurrentBlock; currentBlock += 4)
{
// This line will swap endian on big endian and keep endian on little endian.
w[roundPos++] = (unsigned int) sarray[currentBlock + 3]
| (((unsigned int) sarray[currentBlock + 2]) << 8)
| (((unsigned int) sarray[currentBlock + 1]) << 16)
| (((unsigned int) sarray[currentBlock]) << 24);
}
innerHash(result, w);
}
// Handle the last and not full 64 byte block if existing.
endCurrentBlock = bytelength - currentBlock;
clearWBuffert(w);
int lastBlockBytes = 0;
for (;lastBlockBytes < endCurrentBlock; ++lastBlockBytes)
{
w[lastBlockBytes >> 2] |= (unsigned int) sarray[lastBlockBytes + currentBlock] << ((3 - (lastBlockBytes & 3)) << 3);
}
w[lastBlockBytes >> 2] |= 0x80 << ((3 - (lastBlockBytes & 3)) << 3);
if (endCurrentBlock >= 56)
{
innerHash(result, w);
clearWBuffert(w);
}
w[15] = bytelength << 3;
innerHash(result, w);
// Store hash in result pointer, and make sure we get in in the correct order on both endian models.
for (int hashByte = 20; --hashByte >= 0;)
{
hash[hashByte] = (result[hashByte >> 2] >> (((3 - hashByte) & 0x3) << 3)) & 0xff;
}
}
void toHexString(const unsigned char* hash, char* hexstring)
{
const char hexDigits[] = { "0123456789abcdef" };
for (int hashByte = 20; --hashByte >= 0;)
{
hexstring[hashByte << 1] = hexDigits[(hash[hashByte] >> 4) & 0xf];
hexstring[(hashByte << 1) + 1] = hexDigits[hash[hashByte] & 0xf];
}
hexstring[40] = 0;
}
} // namespace sha1
+49
View File
@@ -0,0 +1,49 @@
/*
Copyright (c) 2011, Micael Hildenborg
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 Micael Hildenborg 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 Micael Hildenborg ''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 Micael Hildenborg 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 SHA1_DEFINED
#define SHA1_DEFINED
namespace sha1
{
/**
@param src points to any kind of data to be hashed.
@param bytelength the number of bytes to hash from the src pointer.
@param hash should point to a buffer of at least 20 bytes of size for storing the sha1 result in.
*/
void calc(const void* src, const int bytelength, unsigned char* hash);
/**
@param hash is 20 bytes of sha1 hash. This is the same data that is the result from the calc function.
@param hexstring should point to a buffer of at least 41 bytes of size for storing the hexadecimal representation of the hash. A zero will be written at position 40, so the buffer will be a valid zero ended string.
*/
void toHexString(const unsigned char* hash, char* hexstring);
} // namespace sha1
#endif // SHA1_DEFINED
+162 -384
View File
@@ -1,406 +1,184 @@
/*
* sha1.hpp
*
* Copyright (C) 1998, 2009
* Paul E. Jones <paulej@packetizer.com>
* All Rights Reserved.
*
* Modifications were done in 2012-13 by Peter Thorson (webmaster@zaphoyd.com)
* to allow header only usage of the library and use C++ features to better
* support C++ usage. These changes are distributed under the original freeware
* license included below
*
* Freeware Public License (FPL)
*
* This software is licensed as "freeware." Permission to distribute
* this software in source and binary forms, including incorporation
* into other products, is hereby granted without a fee. THIS SOFTWARE
* IS PROVIDED 'AS IS' AND WITHOUT ANY EXPRESSED OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHOR SHALL NOT BE HELD
* LIABLE FOR ANY DAMAGES RESULTING FROM THE USE OF THIS SOFTWARE, EITHER
* DIRECTLY OR INDIRECTLY, INCLUDING, BUT NOT LIMITED TO, LOSS OF DATA
* OR DATA BEING RENDERED INACCURATE.
*
*****************************************************************************
*
* Description:
* This class implements the Secure Hashing Standard as defined
* in FIPS PUB 180-1 published April 17, 1995.
*
* Many of the variable names in this class, especially the single
* character names, were used because those were the names used
* in the publication.
*
* The Secure Hashing Standard, which uses the Secure Hashing
* Algorithm (SHA), produces a 160-bit message digest for a
* given data stream. In theory, it is highly improbable that
* two messages will produce the same message digest. Therefore,
* this algorithm can serve as a means of providing a "fingerprint"
* for a message.
*
* Portability Issues:
* SHA-1 is defined in terms of 32-bit "words". This code was
* written with the expectation that the processor has at least
* a 32-bit machine word size. If the machine word size is larger,
* the code should still function properly. One caveat to that
* is that the input functions taking characters and character arrays
* assume that only 8 bits of information are stored in each character.
*
* Caveats:
* SHA-1 is designed to work with messages less than 2^64 bits long.
* Although SHA-1 allows a message digest to be generated for
* messages of any number of bits less than 2^64, this implementation
* only works with messages with a length that is a multiple of 8
* bits.
*
*****************************************************************************
*****
sha1.hpp is a repackaging of the sha1.cpp and sha1.h files from the shallsha1
library (http://code.google.com/p/smallsha1/) into a single header suitable for
use as a header only library. This conversion was done by Peter Thorson
(webmaster@zaphoyd.com) in 2013. All modifications to the code are redistributed
under the same license as the original, which is listed below.
*****
Copyright (c) 2011, Micael Hildenborg
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 Micael Hildenborg 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 Micael Hildenborg ''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 Micael Hildenborg 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 _SHA1_H_
#define _SHA1_H_
#include <websocketpp/common/stdint.hpp>
#ifndef SHA1_DEFINED
#define SHA1_DEFINED
namespace websocketpp {
namespace sha1 {
/// Provides SHA1 hashing functionality
class sha1 {
public:
sha1() {
reset();
}
virtual ~sha1() {}
/// Re-initialize the class
void reset() {
length_low = 0;
length_high = 0;
message_block_index = 0;
H[0] = 0x67452301;
H[1] = 0xEFCDAB89;
H[2] = 0x98BADCFE;
H[3] = 0x10325476;
H[4] = 0xC3D2E1F0;
computed = false;
corrupted = false;
}
/// Extract the message digest as a raw integer array
/**
* @param [out] message_digest_array Integer array to store the message in
* @return Whether or not the extraction was sucessful
*/
bool get_raw_digest(uint32_t * message_digest_array) {
if (corrupted) {
return false;
namespace // local
{
// Rotate an integer value to left.
inline const unsigned int rol(const unsigned int value,
const unsigned int steps)
{
return ((value << steps) | (value >> (32 - steps)));
}
if (!computed) {
pad_message();
computed = true;
// Sets the first 16 integers in the buffert to zero.
// Used for clearing the W buffert.
inline void clearWBuffert(unsigned int* buffert)
{
for (int pos = 16; --pos >= 0;)
{
buffert[pos] = 0;
}
}
for (int i = 0; i < 5; i++) {
message_digest_array[i] = H[i];
}
inline void innerHash(unsigned int* result, unsigned int* w)
{
unsigned int a = result[0];
unsigned int b = result[1];
unsigned int c = result[2];
unsigned int d = result[3];
unsigned int e = result[4];
return true;
}
int round = 0;
/// Provide input to SHA1
/**
* @param [in] message_array The input bytes
* @param [in] length Length of the message array
*/
void input(unsigned char const * message_array, uint32_t length) {
if (!length) {
return;
}
#define sha1macro(func,val) \
{ \
const unsigned int t = rol(a, 5) + (func) + e + val + w[round]; \
e = d; \
d = c; \
c = rol(b, 30); \
b = a; \
a = t; \
}
if (computed || corrupted) {
corrupted = true;
return;
}
while (length-- && !corrupted) {
// Suppresses Visual Studio code analysis for write overrun. It doesn't know the
// index into Message_Block is protected by checking length.
//
// TODO: is there a more compatible way to write the original code to avoid
// this sort of warning?
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(suppress: 6386)
#endif
message_block[message_block_index++] = (*message_array & 0xFF);
#ifdef _MSC_VER
#pragma warning(pop)
#endif
length_low += 8;
length_low &= 0xFFFFFFFF; // Force it to 32 bits
if (length_low == 0) {
length_high++;
length_high &= 0xFFFFFFFF; // Force it to 32 bits
if (length_high == 0) {
corrupted = true; // Message is too long
}
while (round < 16)
{
sha1macro((b & c) | (~b & d), 0x5a827999)
++round;
}
while (round < 20)
{
w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1);
sha1macro((b & c) | (~b & d), 0x5a827999)
++round;
}
while (round < 40)
{
w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1);
sha1macro(b ^ c ^ d, 0x6ed9eba1)
++round;
}
while (round < 60)
{
w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1);
sha1macro((b & c) | (b & d) | (c & d), 0x8f1bbcdc)
++round;
}
while (round < 80)
{
w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1);
sha1macro(b ^ c ^ d, 0xca62c1d6)
++round;
}
if (message_block_index == 64) {
process_message_block();
#undef sha1macro
result[0] += a;
result[1] += b;
result[2] += c;
result[3] += d;
result[4] += e;
}
} // namespace
/**
@param src points to any kind of data to be hashed.
@param bytelength the number of bytes to hash from the src pointer.
@param hash should point to a buffer of at least 20 bytes of size for storing the sha1 result in.
*/
inline void calc(const void* src, const int bytelength, unsigned char* hash) {
// Init the result array.
unsigned int result[5] = { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 };
// Cast the void src pointer to be the byte array we can work with.
const unsigned char* sarray = (const unsigned char*) src;
// The reusable round buffer
unsigned int w[80];
// Loop through all complete 64byte blocks.
const int endOfFullBlocks = bytelength - 64;
int endCurrentBlock;
int currentBlock = 0;
while (currentBlock <= endOfFullBlocks)
{
endCurrentBlock = currentBlock + 64;
// Init the round buffer with the 64 byte block data.
for (int roundPos = 0; currentBlock < endCurrentBlock; currentBlock += 4)
{
// This line will swap endian on big endian and keep endian on little endian.
w[roundPos++] = (unsigned int) sarray[currentBlock + 3]
| (((unsigned int) sarray[currentBlock + 2]) << 8)
| (((unsigned int) sarray[currentBlock + 1]) << 16)
| (((unsigned int) sarray[currentBlock]) << 24);
}
innerHash(result, w);
}
message_array++;
// Handle the last and not full 64 byte block if existing.
endCurrentBlock = bytelength - currentBlock;
clearWBuffert(w);
int lastBlockBytes = 0;
for (;lastBlockBytes < endCurrentBlock; ++lastBlockBytes)
{
w[lastBlockBytes >> 2] |= (unsigned int) sarray[lastBlockBytes + currentBlock] << ((3 - (lastBlockBytes & 3)) << 3);
}
w[lastBlockBytes >> 2] |= 0x80 << ((3 - (lastBlockBytes & 3)) << 3);
if (endCurrentBlock >= 56)
{
innerHash(result, w);
clearWBuffert(w);
}
w[15] = bytelength << 3;
innerHash(result, w);
// Store hash in result pointer, and make sure we get in in the correct order on both endian models.
for (int hashByte = 20; --hashByte >= 0;)
{
hash[hashByte] = (result[hashByte >> 2] >> (((3 - hashByte) & 0x3) << 3)) & 0xff;
}
}
/// Provide input to SHA1
/**
* Overload with signed message array
*
* @param [in] message_array The input bytes
* @param [in] length Length of the message array
*/
void input(char const * message_array, uint32_t length) {
input(reinterpret_cast<const unsigned char *>(message_array), length);
}
/// Provide input to SHA1
/**
* Overload with a single unsigned char
*
* @param [in] message_element The character to input
*/
void input(unsigned char message_element) {
input(&message_element, 1);
}
/// Provide input to SHA1
/**
* Overload with a single signed char
*
* @param [in] message_element The character to input
*/
void input(char message_element) {
input(reinterpret_cast<unsigned char *>(&message_element), 1);
}
/// Provide input to SHA1
/**
* Overload via signed char array stream input
*
* @param [in] message_array The character array to input
*/
sha1& operator<<(char const * message_array) {
char const * p = message_array;
while(*p) {
input(*p);
p++;
}
return *this;
}
/// Provide input to SHA1
/**
* Overload via unsigned char array stream input
*
* @param [in] message_array The character array to input
*/
sha1& operator<<(unsigned char const * message_array) {
unsigned char const * p = message_array;
while(*p) {
input(*p);
p++;
}
return *this;
}
/// Provide input to SHA1
/**
* Overload via signed char stream input
*
* @param [in] message_element The character to input
*/
sha1& operator<<(char message_element) {
input((unsigned char *) &message_element, 1);
return *this;
}
/// Provide input to SHA1
/**
* Overload via unsigned char stream input
*
* @param [in] message_element The character to input
*/
sha1& operator<<(unsigned char message_element) {
input(&message_element, 1);
return *this;
}
private:
/// Process the next 512 bits of the message
/**
* Many of the variable names in this function, especially the single
* character names, were used because those were the names used
* in the publication.
*/
void process_message_block() {
// Constants defined for SHA-1
uint32_t const K[] = { 0x5A827999,
0x6ED9EBA1,
0x8F1BBCDC,
0xCA62C1D6 };
uint32_t temp; // Temporary word value
uint32_t W[80]; // Word sequence
uint32_t A, B, C, D, E; // Word buffers
// Initialize the first 16 words in the array W
for (int t = 0; t < 16; t++) {
W[t] = ((uint32_t) message_block[t * 4]) << 24;
W[t] |= ((uint32_t) message_block[t * 4 + 1]) << 16;
W[t] |= ((uint32_t) message_block[t * 4 + 2]) << 8;
W[t] |= ((uint32_t) message_block[t * 4 + 3]);
}
for (int t = 16; t < 80; t++) {
W[t] = CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
}
A = H[0];
B = H[1];
C = H[2];
D = H[3];
E = H[4];
for (int t = 0; t < 20; t++) {
temp = CircularShift(5,A) + ((B & C) | ((~B) & D)) + E + W[t] + K[0];
temp &= 0xFFFFFFFF;
E = D;
D = C;
C = CircularShift(30,B);
B = A;
A = temp;
}
for (int t = 20; t < 40; t++) {
temp = CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
temp &= 0xFFFFFFFF;
E = D;
D = C;
C = CircularShift(30,B);
B = A;
A = temp;
}
for (int t = 40; t < 60; t++) {
temp = CircularShift(5,A) +
((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
temp &= 0xFFFFFFFF;
E = D;
D = C;
C = CircularShift(30,B);
B = A;
A = temp;
}
for (int t = 60; t < 80; t++) {
temp = CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
temp &= 0xFFFFFFFF;
E = D;
D = C;
C = CircularShift(30,B);
B = A;
A = temp;
}
H[0] = (H[0] + A) & 0xFFFFFFFF;
H[1] = (H[1] + B) & 0xFFFFFFFF;
H[2] = (H[2] + C) & 0xFFFFFFFF;
H[3] = (H[3] + D) & 0xFFFFFFFF;
H[4] = (H[4] + E) & 0xFFFFFFFF;
message_block_index = 0;
}
/// Pads the current message block to 512 bits
/**
* According to the standard, the message must be padded to an even
* 512 bits. The first padding bit must be a '1'. The last 64 bits
* represent the length of the original message. All bits in between
* should be 0. This function will pad the message according to those
* rules by filling the message_block array accordingly. It will also
* call ProcessMessageBlock() appropriately. When it returns, it
* can be assumed that the message digest has been computed.
*/
void pad_message() {
// Check to see if the current message block is too small to hold
// the initial padding bits and length. If so, we will pad the
// block, process it, and then continue padding into a second block.
if (message_block_index > 55) {
message_block[message_block_index++] = 0x80;
while(message_block_index < 64) {
message_block[message_block_index++] = 0;
}
process_message_block();
while(message_block_index < 56) {
message_block[message_block_index++] = 0;
}
} else {
message_block[message_block_index++] = 0x80;
while(message_block_index < 56) {
message_block[message_block_index++] = 0;
}
}
// Store the message length as the last 8 octets
message_block[56] = (length_high >> 24) & 0xFF;
message_block[57] = (length_high >> 16) & 0xFF;
message_block[58] = (length_high >> 8) & 0xFF;
message_block[59] = (length_high) & 0xFF;
message_block[60] = (length_low >> 24) & 0xFF;
message_block[61] = (length_low >> 16) & 0xFF;
message_block[62] = (length_low >> 8) & 0xFF;
message_block[63] = (length_low) & 0xFF;
process_message_block();
}
/// Performs a circular left shift operation
/**
* @param [in] bits How many bits to shift
* @param [in] word The word to shift
* @return The shifted word
*/
inline uint32_t CircularShift(int bits, uint32_t word) {
return ((word << bits) & 0xFFFFFFFF) | ((word & 0xFFFFFFFF) >> (32-bits));
}
uint32_t H[5]; // Message digest buffers
uint32_t length_low; // Message length in bits
uint32_t length_high; // Message length in bits
unsigned char message_block[64]; // 512-bit message blocks
int message_block_index; // Index into message block array
bool computed; // Is the digest computed?
bool corrupted; // Is the message digest corruped?
};
} // namespace sha1
} // namespace websocketpp
#endif // _SHA1_H_
#endif // SHA1_DEFINED
@@ -45,6 +45,11 @@ namespace transport {
*/
namespace asio {
// Forward declaration of class endpoint so that it can be friended/referenced
// before being included.
template <typename config>
class endpoint;
typedef lib::function<void(boost::system::error_code const &)>
socket_shutdown_handler;
@@ -81,9 +81,16 @@ public:
/// Type of a pointer to the ASIO io_service being used
typedef boost::asio::io_service* io_service_ptr;
/// Type of a pointer to the ASIO io_service::strand being used
typedef lib::shared_ptr<boost::asio::io_service::strand> strand_ptr;
/// Type of a pointer to the ASIO timer class
typedef lib::shared_ptr<boost::asio::deadline_timer> timer_ptr;
// connection is friends with its associated endpoint to allow the endpoint
// to call private/protected utility methods that we don't want to expose
// to the public api.
friend class endpoint<config>;
// generate and manage our own io_service
explicit connection(bool is_server, alog_type& alog, elog_type& elog)
: m_is_server(is_server)
@@ -102,29 +109,13 @@ public:
return socket_con_type::is_secure();
}
/// Finish constructing the transport
/// Sets the tcp init handler
/**
* init_asio is called once immediately after construction to initialize
* boost::asio components to the io_service
* The tcp init handler is called after the tcp connection has been
* established.
*
* TODO: this method is not protected because the endpoint needs to call it.
* need to figure out if there is a way to friend the endpoint safely across
* different compilers.
*
* @param io_service A pointer to the io_service to register with this
* connection
*
* @return Status code for the success or failure of the initialization
* @param h The handler to call on tcp init.
*/
lib::error_code init_asio (io_service_ptr io_service) {
// do we need to store or use the io_service at this level?
m_io_service = io_service;
//m_strand.reset(new boost::asio::strand(*io_service));
return socket_con_type::init_asio(io_service, m_is_server);
}
void set_tcp_init_handler(tcp_init_handler h) {
m_tcp_init_handler = h;
}
@@ -251,26 +242,6 @@ public:
return m_connection_hdl;
}
/// initialize the proxy buffers and http parsers
/**
*
* @param authority The address of the server we want the proxy to tunnel to
* in the format of a URI authority (host:port)
*/
lib::error_code proxy_init(const std::string & authority) {
if (!m_proxy_data) {
return websocketpp::error::make_error_code(
websocketpp::error::invalid_state);
}
m_proxy_data->req.set_version("HTTP/1.1");
m_proxy_data->req.set_method("CONNECT");
m_proxy_data->req.set_uri(authority);
m_proxy_data->req.replace_header("Host",authority);
return lib::error_code();
}
/// Call back a function after a period of time.
/**
* Sets a timer that calls back a function after the specified period of
@@ -294,13 +265,13 @@ public:
);
new_timer->async_wait(
lib::bind(
m_strand->wrap(lib::bind(
&type::handle_timer,
get_shared(),
new_timer,
callback,
lib::placeholders::_1
)
))
);
return new_timer;
@@ -311,10 +282,10 @@ public:
* The timer pointer is included to ensure the timer isn't destroyed until
* after it has expired.
*
* TODO: candidate for protected status
*
* @param t Pointer to the timer in question
*
* @param callback The function to call back
*
* @param ec The status code
*/
void handle_timer(timer_ptr t, timer_handler callback, const
@@ -332,6 +303,11 @@ public:
}
}
protected:
/// Get a pointer to this connection's strand
strand_ptr get_strand() {
return m_strand;
}
/// Initialize transport for reading
/**
* init_asio is called once immediately after construction to initialize
@@ -367,6 +343,47 @@ protected:
);
}
/// initialize the proxy buffers and http parsers
/**
*
* @param authority The address of the server we want the proxy to tunnel to
* in the format of a URI authority (host:port)
*
* @return Status code indicating what errors occurred, if any
*/
lib::error_code proxy_init(std::string const & authority) {
if (!m_proxy_data) {
return websocketpp::error::make_error_code(
websocketpp::error::invalid_state);
}
m_proxy_data->req.set_version("HTTP/1.1");
m_proxy_data->req.set_method("CONNECT");
m_proxy_data->req.set_uri(authority);
m_proxy_data->req.replace_header("Host",authority);
return lib::error_code();
}
/// Finish constructing the transport
/**
* init_asio is called once immediately after construction to initialize
* boost::asio components to the io_service
*
* @param io_service A pointer to the io_service to register with this
* connection
*
* @return Status code for the success or failure of the initialization
*/
lib::error_code init_asio (io_service_ptr io_service) {
// do we need to store or use the io_service at this level?
m_io_service = io_service;
m_strand.reset(new boost::asio::strand(*io_service));
return socket_con_type::init_asio(io_service, m_strand, m_is_server);
}
void handle_pre_init(init_handler callback, const lib::error_code& ec) {
if (m_alog.static_test(log::alevel::devel)) {
m_alog.write(log::alevel::devel,"asio connection handle pre_init");
@@ -497,12 +514,12 @@ protected:
boost::asio::async_write(
socket_con_type::get_next_layer(),
m_bufs,
lib::bind(
m_strand->wrap(lib::bind(
&type::handle_proxy_write,
get_shared(),
callback,
lib::placeholders::_1
)
))
);
}
@@ -568,13 +585,13 @@ protected:
socket_con_type::get_next_layer(),
m_proxy_data->read_buf,
"\r\n\r\n",
lib::bind(
m_strand->wrap(lib::bind(
&type::handle_proxy_read,
get_shared(),
callback,
lib::placeholders::_1,
lib::placeholders::_2
)
))
);
}
@@ -680,13 +697,13 @@ protected:
socket_con_type::get_socket(),
boost::asio::buffer(buf,len),
boost::asio::transfer_at_least(num_bytes),
lib::bind(
m_strand->wrap(lib::bind(
&type::handle_async_read,
get_shared(),
handler,
lib::placeholders::_1,
lib::placeholders::_2
)
))
);
}
@@ -718,12 +735,12 @@ protected:
boost::asio::async_write(
socket_con_type::get_socket(),
m_bufs,
lib::bind(
m_strand->wrap(lib::bind(
&type::handle_async_write,
get_shared(),
handler,
lib::placeholders::_1
)
))
);
}
@@ -737,12 +754,12 @@ protected:
boost::asio::async_write(
socket_con_type::get_socket(),
m_bufs,
lib::bind(
m_strand->wrap(lib::bind(
&type::handle_async_write,
get_shared(),
handler,
lib::placeholders::_1
)
))
);
}
@@ -773,16 +790,14 @@ protected:
/// Trigger the on_interrupt handler
/**
* This needs to be thread safe
*
* Might need a strand at some point?
*/
lib::error_code interrupt(interrupt_handler handler) {
m_io_service->post(handler);
m_io_service->post(m_strand->wrap(handler));
return lib::error_code();
}
lib::error_code dispatch(dispatch_handler handler) {
m_io_service->post(handler);
m_io_service->post(m_strand->wrap(handler));
return lib::error_code();
}
@@ -904,8 +919,10 @@ private:
lib::shared_ptr<proxy_data> m_proxy_data;
// transport resources
io_service_ptr m_io_service;
connection_hdl m_connection_hdl;
io_service_ptr m_io_service;
strand_ptr m_strand;
connection_hdl m_connection_hdl;
std::vector<boost::asio::const_buffer> m_bufs;
// Handlers
@@ -574,13 +574,12 @@ public:
m_acceptor->async_accept(
tcon->get_raw_socket(),
lib::bind(
tcon->get_strand()->wrap(lib::bind(
&type::handle_accept,
this,
tcon->get_handle(),
callback,
lib::placeholders::_1
)
))
);
}
@@ -612,18 +611,19 @@ protected:
m_elog = e;
}
void handle_accept(connection_hdl hdl, accept_handler callback,
const boost::system::error_code& error)
void handle_accept(accept_handler callback, boost::system::error_code const
& boost_ec)
{
if (error) {
//con->terminate();
// TODO: Better translation of errors at this point
callback(hdl,make_error_code(error::pass_through));
return;
lib::error_code ret_ec;
m_alog->write(log::alevel::devel, "asio::handle_accept");
if (boost_ec) {
log_err(log::elevel::devel,"asio handle_accept",boost_ec);
ret_ec = make_error_code(error::pass_through);
}
//con->start();
callback(hdl,lib::error_code());
callback(ret_ec);
}
/// Initiate a new connection
@@ -649,13 +649,13 @@ protected:
uri_ptr pu(new uri(proxy));
if (!pu->get_valid()) {
cb(tcon->get_handle(),make_error_code(error::proxy_invalid));
cb(make_error_code(error::proxy_invalid));
return;
}
ec = tcon->proxy_init(u->get_authority());
if (ec) {
cb(tcon->get_handle(),ec);
cb(ec);
return;
}
@@ -672,12 +672,11 @@ protected:
timer_ptr dns_timer;
dns_timer = set_timer(
dns_timer = tcon->set_timer(
config::timeout_dns_resolve,
lib::bind(
&type::handle_resolve_timeout,
this,
tcon,
dns_timer,
cb,
lib::placeholders::_1
@@ -686,7 +685,7 @@ protected:
m_resolver->async_resolve(
query,
lib::bind(
tcon->get_strand()->wrap(lib::bind(
&type::handle_resolve,
this,
tcon,
@@ -694,12 +693,12 @@ protected:
cb,
lib::placeholders::_1,
lib::placeholders::_2
)
))
);
}
void handle_resolve_timeout(transport_con_ptr tcon, timer_ptr dns_timer,
connect_handler callback, const lib::error_code & ec)
void handle_resolve_timeout(timer_ptr dns_timer, connect_handler callback,
lib::error_code const & ec)
{
lib::error_code ret_ec;
@@ -718,11 +717,11 @@ protected:
m_alog->write(log::alevel::devel,"DNS resolution timed out");
m_resolver->cancel();
callback(tcon->get_handle(),ret_ec);
callback(ret_ec);
}
void handle_resolve(transport_con_ptr tcon, timer_ptr dns_timer,
connect_handler callback, const boost::system::error_code& ec,
connect_handler callback, boost::system::error_code const & ec,
boost::asio::ip::tcp::resolver::iterator iterator)
{
if (ec == boost::asio::error::operation_aborted ||
@@ -736,7 +735,7 @@ protected:
if (ec) {
log_err(log::elevel::info,"asio async_resolve",ec);
callback(tcon->get_handle(),make_error_code(error::pass_through));
callback(make_error_code(error::pass_through));
return;
}
@@ -756,10 +755,10 @@ protected:
timer_ptr con_timer;
con_timer = set_timer(
con_timer = tcon->set_timer(
config::timeout_connect,
lib::bind(
&type::handle_resolve_timeout,
&type::handle_connect_timeout,
this,
tcon,
con_timer,
@@ -771,19 +770,19 @@ protected:
boost::asio::async_connect(
tcon->get_raw_socket(),
iterator,
lib::bind(
tcon->get_strand()->wrap(lib::bind(
&type::handle_connect,
this,
tcon,
con_timer,
callback,
lib::placeholders::_1
)
))
);
}
void handle_connect_timeout(transport_con_ptr tcon, timer_ptr con_timer,
connect_handler callback, const lib::error_code & ec)
connect_handler callback, lib::error_code const & ec)
{
lib::error_code ret_ec;
@@ -802,11 +801,11 @@ protected:
m_alog->write(log::alevel::devel,"TCP connect timed out");
tcon->cancel_socket();
callback(tcon->get_handle(),ret_ec);
callback(ret_ec);
}
void handle_connect(transport_con_ptr tcon, timer_ptr con_timer,
connect_handler callback, const boost::system::error_code& ec)
connect_handler callback, boost::system::error_code const & ec)
{
if (ec == boost::asio::error::operation_aborted ||
con_timer->expires_from_now().is_negative())
@@ -819,7 +818,7 @@ protected:
if (ec) {
log_err(log::elevel::info,"asio async_connect",ec);
callback(tcon->get_handle(),make_error_code(error::pass_through));
callback(make_error_code(error::pass_through));
return;
}
@@ -828,7 +827,7 @@ protected:
"Async connect to "+tcon->get_remote_endpoint()+" successful.");
}
callback(tcon->get_handle(),lib::error_code());
callback(lib::error_code());
}
bool is_listening() const {
@@ -58,6 +58,8 @@ public:
/// Type of a pointer to the ASIO io_service being used
typedef boost::asio::io_service* io_service_ptr;
/// Type of a pointer to the ASIO io_service strand being used
typedef lib::shared_ptr<boost::asio::io_service::strand> strand_ptr;
/// Type of a shared pointer to the socket being used.
typedef lib::shared_ptr<boost::asio::ip::tcp::socket> socket_ptr;
@@ -152,7 +154,9 @@ protected:
* @param strand A shared pointer to the connection's asio strand
* @param is_server Whether or not the endpoint is a server or not.
*/
lib::error_code init_asio (io_service_ptr service, bool is_server) {
lib::error_code init_asio (io_service_ptr service, strand_ptr strand,
bool is_server)
{
if (m_state != UNINITIALIZED) {
return socket::make_error_code(socket::error::invalid_state);
}
@@ -68,6 +68,8 @@ public:
typedef lib::shared_ptr<socket_type> socket_ptr;
/// Type of a pointer to the ASIO io_service being used
typedef boost::asio::io_service* io_service_ptr;
/// Type of a pointer to the ASIO io_service strand being used
typedef lib::shared_ptr<boost::asio::io_service::strand> strand_ptr;
/// Type of a shared pointer to the ASIO TLS context being used
typedef lib::shared_ptr<boost::asio::ssl::context> context_ptr;
@@ -174,9 +176,12 @@ protected:
* boost::asio components to the io_service
*
* @param service A pointer to the endpoint's io_service
* @param strand A pointer to the connection's strand
* @param is_server Whether or not the endpoint is a server or not.
*/
lib::error_code init_asio (io_service_ptr service, bool is_server) {
lib::error_code init_asio (io_service_ptr service, strand_ptr strand,
bool is_server)
{
if (!m_tls_init_handler) {
return socket::make_error_code(socket::error::missing_tls_init_handler);
}
@@ -188,6 +193,7 @@ protected:
m_socket.reset(new socket_type(*service,*m_context));
m_io_service = service;
m_strand = strand;
m_is_server = is_server;
return lib::error_code();
@@ -224,12 +230,12 @@ protected:
// TLS handshake
m_socket->async_handshake(
get_handshake_type(),
lib::bind(
m_strand->wrap(lib::bind(
&type::handle_init,
get_shared(),
callback,
lib::placeholders::_1
)
))
);
}
@@ -278,6 +284,7 @@ private:
}
io_service_ptr m_io_service;
strand_ptr m_strand;
context_ptr m_context;
socket_ptr m_socket;
bool m_is_server;
@@ -71,12 +71,10 @@ namespace websocketpp {
namespace transport {
/// The type and signature of the callback passed to the accept method
typedef lib::function<void(connection_hdl, lib::error_code const &)>
accept_handler;
typedef lib::function<void(lib::error_code const &)> accept_handler;
/// The type and signature of the callback passed to the connect method
typedef lib::function<void(connection_hdl, lib::error_code const &)>
connect_handler;
typedef lib::function<void(lib::error_code const &)> connect_handler;
} // namespace transport
} // namespace websocketpp
@@ -141,7 +141,7 @@ protected:
* @param cb The function to call back with the results when complete.
*/
void async_connect(transport_con_ptr tcon, uri_ptr u, connect_handler cb) {
cb(tcon->get_handle(),lib::error_code());
cb(lib::error_code());
}
/// Initialize a connection
+4 -1
View File
@@ -138,7 +138,10 @@ public:
std::string port = "";
while (state == 1) {
if (it == uri.end()) {
state = 3;
// state is not used after this point presently.
// this should be re-enabled if it ever is needed in a future
// refactoring
//state = 3;
break;
} else if (*it == '/') {
state = 3;
+27 -2
View File
@@ -1,5 +1,30 @@
// Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
// See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details.
/*
* The following code is adapted from code originally written by Bjoern
* Hoehrmann <bjoern@hoehrmann.de>. See
* http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details.
*
* The original license:
*
* Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef UTF8_VALIDATOR_HPP
#define UTF8_VALIDATOR_HPP
+2 -2
View File
@@ -50,10 +50,10 @@ static int const patch_version = 0;
* This is a textual flag indicating the type and number for pre-release
* versions (dev, alpha, beta, rc). This will be blank for release versions.
*/
static char const prerelease_flag[] = "alpha3";
static char const prerelease_flag[] = "alpha4";
/// Default user agent string
static char const user_agent[] = "WebSocket++/0.3.0-alpha3";
static char const user_agent[] = "WebSocket++/0.3.0-alpha4";
} // namespace websocketpp