update copyright dates and fix whitespace that doesn't match projec style

This commit is contained in:
Peter Thorson
2013-05-05 11:23:31 -05:00
parent 3c9f3206c5
commit d908c1afd2
60 changed files with 2743 additions and 2743 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Peter Thorson. All rights reserved.
* Copyright (c) 2013, 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:
@@ -71,8 +71,8 @@
//#define _WEBSOCKETPP_CPP11_ALIAS_TEMPLATES_
#ifdef _WEBSOCKETPP_CPP11_
#define _WEBSOCKETPP_DELETED_FUNCTIONS_
#define _WEBSOCKETPP_RVALUE_REFERENCES_
#define _WEBSOCKETPP_DELETED_FUNCTIONS_
#define _WEBSOCKETPP_RVALUE_REFERENCES_
#endif
#include <string>

View File

@@ -29,24 +29,24 @@
#define WEBSOCKETPP_COMMON_CHRONO_HPP
#if defined _WEBSOCKETPP_CPP11_STL_ && !defined _WEBSOCKETPP_NO_CPP11_CHRONO_
#ifndef _WEBSOCKETPP_CPP11_CHRONO_
#define _WEBSOCKETPP_CPP11_CHRONO_
#endif
#ifndef _WEBSOCKETPP_CPP11_CHRONO_
#define _WEBSOCKETPP_CPP11_CHRONO_
#endif
#endif
#ifdef _WEBSOCKETPP_CPP11_CHRONO_
#include <chrono>
#include <chrono>
#else
#include <boost/chrono.hpp>
#include <boost/chrono.hpp>
#endif
namespace websocketpp {
namespace lib {
#ifdef _WEBSOCKETPP_CPP11_CHRONO_
using std::chrono::system_clock;
using std::chrono::system_clock;
#else
using boost::chrono::system_clock;
using boost::chrono::system_clock;
#endif
} // namespace lib

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Peter Thorson. All rights reserved.
* Copyright (c) 2013, 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:
@@ -42,44 +42,44 @@
#ifdef _WEBSOCKETPP_CPP11_STL_
// This flag indicates that all of the C++11 language features are available
// to us.
#define _WEBSOCKETPP_NOEXCEPT_TOKEN_ noexcept
#define _WEBSOCKETPP_CONSTEXPR_TOKEN_ constexpr
#define _WEBSOCKETPP_INITIALIZER_LISTS_
// This flag indicates that all of the C++11 language features are available
// to us.
#define _WEBSOCKETPP_NOEXCEPT_TOKEN_ noexcept
#define _WEBSOCKETPP_CONSTEXPR_TOKEN_ constexpr
#define _WEBSOCKETPP_INITIALIZER_LISTS_
#else
// Test for noexcept
#ifdef _WEBSOCKETPP_NOEXCEPT_
// build system says we have noexcept
#define _WEBSOCKETPP_NOEXCEPT_TOKEN_ noexcept
#else
#if __has_feature(cxx_noexcept)
// clang feature detect says we have noexcept
#define _WEBSOCKETPP_NOEXCEPT_TOKEN_ noexcept
#else
// assume we don't have noexcept
#define _WEBSOCKETPP_NOEXCEPT_TOKEN_
#endif
#endif
// Test for constexpr
#ifdef _WEBSOCKETPP_CONSTEXPR_
// build system says we have constexpr
#define _WEBSOCKETPP_CONSTEXPR_TOKEN_ constexpr
#else
#if __has_feature(cxx_constexpr)
// clang feature detect says we have constexpr
#define _WEBSOCKETPP_CONSTEXPR_TOKEN_ constexpr
#else
// assume we don't have constexpr
#define _WEBSOCKETPP_CONSTEXPR_TOKEN_
#endif
#endif
// Enable initializer lists on clang when available.
#if __has_feature(cxx_generalized_initializers)
#define _WEBSOCKETPP_INITIALIZER_LISTS_
#endif
// Test for noexcept
#ifdef _WEBSOCKETPP_NOEXCEPT_
// build system says we have noexcept
#define _WEBSOCKETPP_NOEXCEPT_TOKEN_ noexcept
#else
#if __has_feature(cxx_noexcept)
// clang feature detect says we have noexcept
#define _WEBSOCKETPP_NOEXCEPT_TOKEN_ noexcept
#else
// assume we don't have noexcept
#define _WEBSOCKETPP_NOEXCEPT_TOKEN_
#endif
#endif
// Test for constexpr
#ifdef _WEBSOCKETPP_CONSTEXPR_
// build system says we have constexpr
#define _WEBSOCKETPP_CONSTEXPR_TOKEN_ constexpr
#else
#if __has_feature(cxx_constexpr)
// clang feature detect says we have constexpr
#define _WEBSOCKETPP_CONSTEXPR_TOKEN_ constexpr
#else
// assume we don't have constexpr
#define _WEBSOCKETPP_CONSTEXPR_TOKEN_
#endif
#endif
// Enable initializer lists on clang when available.
#if __has_feature(cxx_generalized_initializers)
#define _WEBSOCKETPP_INITIALIZER_LISTS_
#endif
#endif
#endif // WEBSOCKETPP_COMMON_CPP11_HPP

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Peter Thorson. All rights reserved.
* Copyright (c) 2013, 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:
@@ -29,35 +29,35 @@
#define WEBSOCKETPP_COMMON_FUNCTIONAL_HPP
#if defined _WEBSOCKETPP_CPP11_STL_ && !defined _WEBSOCKETPP_NO_CPP11_FUNCTIONAL_
#ifndef _WEBSOCKETPP_CPP11_FUNCTIONAL_
#define _WEBSOCKETPP_CPP11_FUNCTIONAL_
#endif
#ifndef _WEBSOCKETPP_CPP11_FUNCTIONAL_
#define _WEBSOCKETPP_CPP11_FUNCTIONAL_
#endif
#endif
#ifdef _WEBSOCKETPP_CPP11_FUNCTIONAL_
#include <functional>
#include <functional>
#else
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <boost/function.hpp>
#endif
namespace websocketpp {
namespace lib {
#ifdef _WEBSOCKETPP_CPP11_FUNCTIONAL_
using std::function;
using std::bind;
using std::ref;
namespace placeholders = std::placeholders;
using std::function;
using std::bind;
using std::ref;
namespace placeholders = std::placeholders;
#else
using boost::function;
using boost::bind;
using boost::ref;
namespace placeholders {
// TODO: there has got to be a better way than this
using ::_1;
using ::_2;
}
using boost::function;
using boost::bind;
using boost::ref;
namespace placeholders {
// TODO: there has got to be a better way than this
using ::_1;
using ::_2;
}
#endif
} // namespace lib

View File

@@ -29,34 +29,34 @@
#define WEBSOCKETPP_COMMON_MEMORY_HPP
#if defined _WEBSOCKETPP_CPP11_STL_ && !defined _WEBSOCKETPP_NO_CPP11_MEMORY_
#ifndef _WEBSOCKETPP_CPP11_MEMORY_
#define _WEBSOCKETPP_CPP11_MEMORY_
#endif
#ifndef _WEBSOCKETPP_CPP11_MEMORY_
#define _WEBSOCKETPP_CPP11_MEMORY_
#endif
#endif
#ifdef _WEBSOCKETPP_CPP11_MEMORY_
#include <memory>
#include <memory>
#else
#include <boost/shared_ptr.hpp>
#include <boost/scoped_array.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/pointer_cast.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/scoped_array.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/pointer_cast.hpp>
#endif
namespace websocketpp {
namespace lib {
#ifdef _WEBSOCKETPP_CPP11_MEMORY_
using std::shared_ptr;
using std::weak_ptr;
using std::enable_shared_from_this;
using std::shared_ptr;
using std::weak_ptr;
using std::enable_shared_from_this;
using std::static_pointer_cast;
typedef std::unique_ptr<unsigned char[]> unique_ptr_uchar_array;
#else
using boost::shared_ptr;
using boost::weak_ptr;
using boost::enable_shared_from_this;
using boost::shared_ptr;
using boost::weak_ptr;
using boost::enable_shared_from_this;
using boost::static_pointer_cast;
typedef boost::scoped_array<unsigned char> unique_ptr_uchar_array;

View File

@@ -30,10 +30,10 @@
// For ntohs and htons
#if defined(WIN32)
#include <winsock2.h>
#include <winsock2.h>
#else
//#include <arpa/inet.h>
#include <netinet/in.h>
//#include <arpa/inet.h>
#include <netinet/in.h>
#endif
namespace websocketpp {
@@ -41,7 +41,7 @@ namespace lib {
namespace net {
inline bool is_little_endian() {
short int val = 0x1;
short int val = 0x1;
char *ptr = (char*)&val;
return (ptr[0] == 1);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Peter Thorson. All rights reserved.
* Copyright (c) 2013, 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:
@@ -29,24 +29,24 @@
#define WEBSOCKETPP_COMMON_RANDOM_DEVICE_HPP
#if defined _WEBSOCKETPP_CPP11_STL_ && !defined _WEBSOCKETPP_NO_CPP11_RANDOM_DEVICE_
#ifndef _WEBSOCKETPP_CPP11_RANDOM_DEVICE_
#define _WEBSOCKETPP_CPP11_RANDOM_DEVICE_
#endif
#ifndef _WEBSOCKETPP_CPP11_RANDOM_DEVICE_
#define _WEBSOCKETPP_CPP11_RANDOM_DEVICE_
#endif
#endif
#ifdef _WEBSOCKETPP_CPP11_RANDOM_DEVICE_
#include <random>
#include <random>
#else
#include <boost/version.hpp>
#if (BOOST_VERSION/100000) == 1 && ((BOOST_VERSION/100)%1000) > 46
#include <boost/random/uniform_int_distribution.hpp>
#include <boost/random/random_device.hpp>
#elif (BOOST_VERSION/100000) == 1 && ((BOOST_VERSION/100)%1000) >= 43
#include <boost/nondet_random.hpp>
#else
// TODO: static_assert(false, "Could not find a suitable random_device")
#endif
#include <boost/version.hpp>
#if (BOOST_VERSION/100000) == 1 && ((BOOST_VERSION/100)%1000) > 46
#include <boost/random/uniform_int_distribution.hpp>
#include <boost/random/random_device.hpp>
#elif (BOOST_VERSION/100000) == 1 && ((BOOST_VERSION/100)%1000) >= 43
#include <boost/nondet_random.hpp>
#else
// TODO: static_assert(false, "Could not find a suitable random_device")
#endif
#endif
namespace websocketpp {

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Peter Thorson. All rights reserved.
* Copyright (c) 2013, 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:
@@ -29,15 +29,15 @@
#define WEBSOCKETPP_COMMON_REGEX_HPP
#if defined _WEBSOCKETPP_CPP11_STL_ && !defined _WEBSOCKETPP_NO_CPP11_REGEX_
#ifndef _WEBSOCKETPP_CPP11_REGEX_
#define _WEBSOCKETPP_CPP11_REGEX_
#endif
#ifndef _WEBSOCKETPP_CPP11_REGEX_
#define _WEBSOCKETPP_CPP11_REGEX_
#endif
#endif
#ifdef _WEBSOCKETPP_CPP11_REGEX_
#include <regex>
#include <regex>
#else
#include <boost/regex.hpp>
#include <boost/regex.hpp>
#endif
namespace websocketpp {

View File

@@ -29,7 +29,7 @@
#define WEBSOCKETPP_COMMON_STDINT_HPP
#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS 1
#define __STDC_LIMIT_MACROS 1
#endif
#if WIN32 && (_MSC_VER < 1600)

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Peter Thorson. All rights reserved.
* Copyright (c) 2013, 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:
@@ -29,16 +29,16 @@
#define WEBSOCKETPP_COMMON_SYSTEM_ERROR_HPP
#if defined _WEBSOCKETPP_CPP11_STL_ && !defined _WEBSOCKETPP_NO_CPP11_SYSTEM_ERROR_
#ifndef _WEBSOCKETPP_CPP11_SYSTEM_ERROR_
#define _WEBSOCKETPP_CPP11_SYSTEM_ERROR_
#endif
#ifndef _WEBSOCKETPP_CPP11_SYSTEM_ERROR_
#define _WEBSOCKETPP_CPP11_SYSTEM_ERROR_
#endif
#endif
#ifdef _WEBSOCKETPP_CPP11_SYSTEM_ERROR_
#include <system_error>
#include <system_error>
#else
#include <boost/system/error_code.hpp>
#include <boost/system/system_error.hpp>
#include <boost/system/error_code.hpp>
#include <boost/system/system_error.hpp>
#endif
namespace websocketpp {

View File

@@ -29,31 +29,31 @@
#define WEBSOCKETPP_COMMON_THREAD_HPP
#if defined _WEBSOCKETPP_CPP11_STL_ && !defined _WEBSOCKETPP_NO_CPP11_THREAD_
#ifndef _WEBSOCKETPP_CPP11_THREAD_
#define _WEBSOCKETPP_CPP11_THREAD_
#endif
#ifndef _WEBSOCKETPP_CPP11_THREAD_
#define _WEBSOCKETPP_CPP11_THREAD_
#endif
#endif
#ifdef _WEBSOCKETPP_CPP11_THREAD_
#include <thread>
#include <mutex>
#include <thread>
#include <mutex>
#else
#include <boost/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition_variable.hpp>
#include <boost/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition_variable.hpp>
#endif
namespace websocketpp {
namespace lib {
#ifdef _WEBSOCKETPP_CPP11_THREAD_
using std::mutex;
using std::lock_guard;
using std::thread;
using std::mutex;
using std::lock_guard;
using std::thread;
#else
using boost::mutex;
using boost::lock_guard;
using boost::thread;
using boost::mutex;
using boost::lock_guard;
using boost::thread;
#endif
} // namespace lib

View File

@@ -35,8 +35,8 @@ namespace concurrency {
class basic {
public:
typedef lib::mutex mutex_type;
typedef lib::lock_guard<mutex_type> scoped_lock_type;
typedef lib::mutex mutex_type;
typedef lib::lock_guard<mutex_type> scoped_lock_type;
};
} // namespace concurrency

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Peter Thorson. All rights reserved.
* Copyright (c) 2013, 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:
@@ -47,11 +47,11 @@ public:
class fake_lock_guard {
public:
explicit fake_lock_guard(fake_mutex foo) {
//std::cout << "fake_lock_guard constructor: " << this << " mutex: " << &foo << std::endl;
}
~fake_lock_guard() {
explicit fake_lock_guard(fake_mutex foo) {
//std::cout << "fake_lock_guard constructor: " << this << " mutex: " << &foo << std::endl;
}
~fake_lock_guard() {
//std::cout << "fake_lock_guard destructor: " << this << std::endl;
}
};
@@ -60,8 +60,8 @@ public:
class none {
public:
typedef none_impl::fake_mutex mutex_type;
typedef none_impl::fake_lock_guard scoped_lock_type;
typedef none_impl::fake_mutex mutex_type;
typedef none_impl::fake_lock_guard scoped_lock_type;
};
} // namespace concurrency

View File

@@ -42,19 +42,19 @@ namespace config {
struct asio_tls : public core {
typedef asio_tls type;
typedef core::concurrency_type concurrency_type;
typedef core::request_type request_type;
typedef core::response_type response_type;
typedef core::concurrency_type concurrency_type;
typedef core::request_type request_type;
typedef core::response_type response_type;
typedef core::message_type message_type;
typedef core::con_msg_manager_type con_msg_manager_type;
typedef core::endpoint_msg_manager_type endpoint_msg_manager_type;
typedef core::alog_type alog_type;
typedef core::elog_type elog_type;
typedef core::rng_type rng_type;
typedef core::message_type message_type;
typedef core::con_msg_manager_type con_msg_manager_type;
typedef core::endpoint_msg_manager_type endpoint_msg_manager_type;
typedef core::alog_type alog_type;
typedef core::elog_type elog_type;
typedef core::rng_type rng_type;
struct transport_config {
typedef type::concurrency_type concurrency_type;

View File

@@ -42,19 +42,19 @@ namespace config {
struct asio_tls_client : public core_client {
typedef asio_tls_client type;
typedef core_client::concurrency_type concurrency_type;
typedef core_client::request_type request_type;
typedef core_client::response_type response_type;
typedef core_client::concurrency_type concurrency_type;
typedef core_client::request_type request_type;
typedef core_client::response_type response_type;
typedef core_client::message_type message_type;
typedef core_client::con_msg_manager_type con_msg_manager_type;
typedef core_client::endpoint_msg_manager_type endpoint_msg_manager_type;
typedef core_client::alog_type alog_type;
typedef core_client::elog_type elog_type;
typedef core_client::rng_type rng_type;
typedef core_client::message_type message_type;
typedef core_client::con_msg_manager_type con_msg_manager_type;
typedef core_client::endpoint_msg_manager_type endpoint_msg_manager_type;
typedef core_client::alog_type alog_type;
typedef core_client::elog_type elog_type;
typedef core_client::rng_type rng_type;
struct transport_config {
typedef type::concurrency_type concurrency_type;

View File

@@ -35,19 +35,19 @@ namespace websocketpp {
namespace config {
struct asio : public core {
typedef asio type;
typedef core::concurrency_type concurrency_type;
typedef core::request_type request_type;
typedef core::response_type response_type;
typedef asio type;
typedef core::concurrency_type concurrency_type;
typedef core::request_type request_type;
typedef core::response_type response_type;
typedef core::message_type message_type;
typedef core::con_msg_manager_type con_msg_manager_type;
typedef core::endpoint_msg_manager_type endpoint_msg_manager_type;
typedef core::alog_type alog_type;
typedef core::elog_type elog_type;
typedef core::message_type message_type;
typedef core::con_msg_manager_type con_msg_manager_type;
typedef core::endpoint_msg_manager_type endpoint_msg_manager_type;
typedef core::alog_type alog_type;
typedef core::elog_type elog_type;
typedef core::rng_type rng_type;

View File

@@ -37,17 +37,17 @@ namespace config {
struct asio_client : public core_client {
typedef asio_client type;
typedef core_client::concurrency_type concurrency_type;
typedef core_client::request_type request_type;
typedef core_client::response_type response_type;
typedef core_client::concurrency_type concurrency_type;
typedef core_client::request_type request_type;
typedef core_client::response_type response_type;
typedef core_client::message_type message_type;
typedef core_client::con_msg_manager_type con_msg_manager_type;
typedef core_client::endpoint_msg_manager_type endpoint_msg_manager_type;
typedef core_client::alog_type alog_type;
typedef core_client::elog_type elog_type;
typedef core_client::message_type message_type;
typedef core_client::con_msg_manager_type con_msg_manager_type;
typedef core_client::endpoint_msg_manager_type endpoint_msg_manager_type;
typedef core_client::alog_type alog_type;
typedef core_client::elog_type elog_type;
typedef core_client::rng_type rng_type;

View File

@@ -69,28 +69,28 @@ struct core {
// Concurrency policy
typedef websocketpp::concurrency::basic concurrency_type;
// HTTP Parser Policies
typedef http::parser::request request_type;
typedef http::parser::response response_type;
// Message Policies
typedef message_buffer::message<message_buffer::alloc::con_msg_manager>
message_type;
message_type;
typedef message_buffer::alloc::con_msg_manager<message_type>
con_msg_manager_type;
con_msg_manager_type;
typedef message_buffer::alloc::endpoint_msg_manager<con_msg_manager_type>
endpoint_msg_manager_type;
/// Logging policies
typedef websocketpp::log::basic<concurrency_type,
websocketpp::log::elevel> elog_type;
typedef websocketpp::log::basic<concurrency_type,
websocketpp::log::alevel> alog_type;
/// RNG policies
typedef websocketpp::random::none::int_generator<uint32_t> rng_type;
endpoint_msg_manager_type;
/// Logging policies
typedef websocketpp::log::basic<concurrency_type,
websocketpp::log::elevel> elog_type;
typedef websocketpp::log::basic<concurrency_type,
websocketpp::log::alevel> alog_type;
/// RNG policies
typedef websocketpp::random::none::int_generator<uint32_t> rng_type;
struct transport_config {
typedef type::concurrency_type concurrency_type;
typedef type::elog_type elog_type;
@@ -143,7 +143,7 @@ struct core {
websocketpp::log::alevel::all ^ websocketpp::log::alevel::devel;
///
static const size_t connection_read_buffer_size = 512;
static const size_t connection_read_buffer_size = 512;
/// Drop connections immediately on protocol error.
/**

View File

@@ -67,29 +67,29 @@ struct core_client {
// Concurrency policy
typedef websocketpp::concurrency::basic concurrency_type;
// HTTP Parser Policies
typedef http::parser::request request_type;
typedef http::parser::response response_type;
// Message Policies
typedef message_buffer::message<message_buffer::alloc::con_msg_manager>
message_type;
message_type;
typedef message_buffer::alloc::con_msg_manager<message_type>
con_msg_manager_type;
con_msg_manager_type;
typedef message_buffer::alloc::endpoint_msg_manager<con_msg_manager_type>
endpoint_msg_manager_type;
/// Logging policies
typedef websocketpp::log::basic<concurrency_type,
websocketpp::log::elevel> elog_type;
typedef websocketpp::log::basic<concurrency_type,
websocketpp::log::alevel> alog_type;
/// RNG policies
typedef websocketpp::random::random_device::int_generator<uint32_t,
concurrency_type> rng_type;
endpoint_msg_manager_type;
/// Logging policies
typedef websocketpp::log::basic<concurrency_type,
websocketpp::log::elevel> elog_type;
typedef websocketpp::log::basic<concurrency_type,
websocketpp::log::alevel> alog_type;
/// RNG policies
typedef websocketpp::random::random_device::int_generator<uint32_t,
concurrency_type> rng_type;
struct transport_config {
typedef type::concurrency_type concurrency_type;
typedef type::elog_type elog_type;
@@ -142,7 +142,7 @@ struct core_client {
websocketpp::log::alevel::all ^ websocketpp::log::alevel::devel;
///
static const size_t connection_read_buffer_size = 512;
static const size_t connection_read_buffer_size = 512;
/// Drop connections immediately on protocol error.
/**

View File

@@ -69,28 +69,28 @@ struct debug_core {
// Concurrency policy
typedef websocketpp::concurrency::basic concurrency_type;
// HTTP Parser Policies
typedef http::parser::request request_type;
typedef http::parser::response response_type;
// Message Policies
typedef message_buffer::message<message_buffer::alloc::con_msg_manager>
message_type;
message_type;
typedef message_buffer::alloc::con_msg_manager<message_type>
con_msg_manager_type;
con_msg_manager_type;
typedef message_buffer::alloc::endpoint_msg_manager<con_msg_manager_type>
endpoint_msg_manager_type;
/// Logging policies
typedef websocketpp::log::basic<concurrency_type,
websocketpp::log::elevel> elog_type;
typedef websocketpp::log::basic<concurrency_type,
websocketpp::log::alevel> alog_type;
/// RNG policies
typedef websocketpp::random::none::int_generator<uint32_t> rng_type;
endpoint_msg_manager_type;
/// Logging policies
typedef websocketpp::log::basic<concurrency_type,
websocketpp::log::elevel> elog_type;
typedef websocketpp::log::basic<concurrency_type,
websocketpp::log::alevel> alog_type;
/// RNG policies
typedef websocketpp::random::none::int_generator<uint32_t> rng_type;
struct transport_config {
typedef type::concurrency_type concurrency_type;
typedef type::elog_type elog_type;
@@ -143,7 +143,7 @@ struct debug_core {
websocketpp::log::alevel::all;
///
static const size_t connection_read_buffer_size = 512;
static const size_t connection_read_buffer_size = 512;
/// Drop connections immediately on protocol error.
/**

View File

@@ -41,21 +41,21 @@ namespace config {
struct debug_asio_tls : public debug_core {
typedef debug_asio_tls type;
typedef debug_core base;
typedef base::concurrency_type concurrency_type;
typedef base::request_type request_type;
typedef base::response_type response_type;
typedef debug_core base;
typedef base::concurrency_type concurrency_type;
typedef base::request_type request_type;
typedef base::response_type response_type;
typedef base::message_type message_type;
typedef base::con_msg_manager_type con_msg_manager_type;
typedef base::endpoint_msg_manager_type endpoint_msg_manager_type;
typedef base::alog_type alog_type;
typedef base::elog_type elog_type;
typedef base::rng_type rng_type;
typedef base::message_type message_type;
typedef base::con_msg_manager_type con_msg_manager_type;
typedef base::endpoint_msg_manager_type endpoint_msg_manager_type;
typedef base::alog_type alog_type;
typedef base::elog_type elog_type;
typedef base::rng_type rng_type;
struct transport_config {
typedef type::concurrency_type concurrency_type;

View File

@@ -38,17 +38,17 @@ struct debug_asio : public debug_core {
typedef debug_asio type;
typedef debug_core base;
typedef base::concurrency_type concurrency_type;
typedef base::request_type request_type;
typedef base::response_type response_type;
typedef base::concurrency_type concurrency_type;
typedef base::request_type request_type;
typedef base::response_type response_type;
typedef base::message_type message_type;
typedef base::con_msg_manager_type con_msg_manager_type;
typedef base::endpoint_msg_manager_type endpoint_msg_manager_type;
typedef base::alog_type alog_type;
typedef base::elog_type elog_type;
typedef base::message_type message_type;
typedef base::con_msg_manager_type con_msg_manager_type;
typedef base::endpoint_msg_manager_type endpoint_msg_manager_type;
typedef base::alog_type alog_type;
typedef base::elog_type elog_type;
typedef base::rng_type rng_type;

View File

@@ -72,7 +72,7 @@ typedef lib::function<void(connection_hdl)> http_handler;
namespace session {
namespace state {
// externally visible session state (states based on the RFC)
// externally visible session state (states based on the RFC)
enum value {
connecting = 0,
open = 1,
@@ -96,20 +96,20 @@ namespace status {
} // namespace fail
namespace internal_state {
// More granular internal states. These are used for multi-threaded
// connection syncronization and preventing values that are not yet or no
// longer avaliable from being used.
enum value {
USER_INIT = 0,
TRANSPORT_INIT = 1,
READ_HTTP_REQUEST = 2,
WRITE_HTTP_REQUEST = 3,
READ_HTTP_RESPONSE = 4,
WRITE_HTTP_RESPONSE = 5,
PROCESS_HTTP_REQUEST = 6,
PROCESS_CONNECTION = 7
};
// More granular internal states. These are used for multi-threaded
// connection syncronization and preventing values that are not yet or no
// longer avaliable from being used.
enum value {
USER_INIT = 0,
TRANSPORT_INIT = 1,
READ_HTTP_REQUEST = 2,
WRITE_HTTP_REQUEST = 3,
READ_HTTP_RESPONSE = 4,
WRITE_HTTP_RESPONSE = 5,
PROCESS_HTTP_REQUEST = 6,
PROCESS_CONNECTION = 7
};
} // namespace internal_state
} // namespace session
@@ -149,10 +149,10 @@ public:
typedef typename config::request_type request_type;
typedef typename config::response_type response_type;
typedef typename config::message_type message_type;
typedef typename message_type::ptr message_ptr;
typedef typename config::con_msg_manager_type con_msg_manager_type;
typedef typename config::message_type message_type;
typedef typename message_type::ptr message_ptr;
typedef typename config::con_msg_manager_type con_msg_manager_type;
typedef typename con_msg_manager_type::ptr con_msg_manager_ptr;
/// Type of RNG
@@ -174,14 +174,14 @@ public:
, m_state(session::state::connecting)
, m_internal_state(session::internal_state::USER_INIT)
, m_msg_manager(new con_msg_manager_type())
, m_send_buffer_size(0)
, m_write_flag(false)
, m_is_server(is_server)
, m_alog(alog)
, m_elog(elog)
, m_rng(rng)
, m_local_close_code(close::status::abnormal_close)
, m_remote_close_code(close::status::abnormal_close)
, m_send_buffer_size(0)
, m_write_flag(false)
, m_is_server(is_server)
, m_alog(alog)
, m_elog(elog)
, m_rng(rng)
, m_local_close_code(close::status::abnormal_close)
, m_remote_close_code(close::status::abnormal_close)
{
m_alog.write(log::alevel::devel,"connection constructor");
}
@@ -322,21 +322,21 @@ public:
// Uncategorized public methods //
//////////////////////////////////
/// Get the size of the outgoing write buffer (in payload bytes)
/**
* Retrieves the number of bytes in the outgoing write buffer that have not
/// Get the size of the outgoing write buffer (in payload bytes)
/**
* Retrieves the number of bytes in the outgoing write buffer that have not
* already been dispatched to the transport layer. This represents the bytes
* that are presently cancelable without uncleanly ending the websocket
* connection
*
* This method invokes the m_write_lock mutex
*
* @return The current number of bytes in the outgoing send buffer.
*/
size_t get_buffered_amount() const;
*
* @return The current number of bytes in the outgoing send buffer.
*/
size_t get_buffered_amount() const;
/// DEPRECATED: use get_buffered_amount instead
size_t buffered_amount() const {return get_buffered_amount();}
/// DEPRECATED: use get_buffered_amount instead
size_t buffered_amount() const {return get_buffered_amount();}
////////////////////
// Action Methods //
@@ -355,9 +355,9 @@ public:
* frame::opcode::text
*/
lib::error_code send(const std::string& payload, frame::opcode::value op =
frame::opcode::TEXT);
/// Send a message (raw array overload)
frame::opcode::TEXT);
/// Send a message (raw array overload)
/**
* Convenience method to send a message given a raw array and optionally an
* opcode. Default opcode is binary.
@@ -781,7 +781,7 @@ public:
void handle_write(const lib::error_code& ec);
void handle_handshake_read(const lib::error_code& ec,
size_t bytes_transferred);
size_t bytes_transferred);
void handle_read_http_response(const lib::error_code& ec,
size_t bytes_transferred);
@@ -977,8 +977,8 @@ private:
void log_close_result();
// static settings
const std::string m_user_agent;
const std::string m_user_agent;
/// Pointer to the connection handle
connection_hdl m_connection_hdl;
@@ -1040,13 +1040,13 @@ private:
/**
* Lock: m_write_lock
*/
std::queue<message_ptr> m_send_queue;
std::queue<message_ptr> m_send_queue;
/// Size in bytes of the outstanding payloads in the write queue
/**
* Lock: m_write_lock
*/
size_t m_send_buffer_size;
size_t m_send_buffer_size;
/// buffer holding the various parts of the current message being writen
/**
@@ -1074,7 +1074,7 @@ private:
// of the whole connection.
std::vector<std::string> m_requested_subprotocols;
const bool m_is_server;
const bool m_is_server;
alog_type& m_alog;
elog_type& m_elog;

View File

@@ -42,21 +42,21 @@ static const char user_agent[] = "WebSocket++/0.3.0dev";
template <typename connection, typename config>
class endpoint : public config::transport_type, public config::endpoint_base {
public:
// Import appropriate types from our helper class
// See endpoint_types for more details.
typedef endpoint<connection,config> type;
// Import appropriate types from our helper class
// See endpoint_types for more details.
typedef endpoint<connection,config> type;
/// Type of the transport component of this endpoint
typedef typename config::transport_type transport_type;
/// Type of the concurrency component of this endpoint
typedef typename config::concurrency_type concurrency_type;
typedef typename config::concurrency_type concurrency_type;
/// Type of the connections that this endpoint creates
typedef connection connection_type;
typedef connection connection_type;
/// Shared pointer to connection_type
typedef typename connection_type::ptr connection_ptr;
typedef typename connection_type::ptr connection_ptr;
/// Weak pointer to connection type
typedef typename connection_type::weak_ptr connection_weak_ptr;
typedef typename connection_type::weak_ptr connection_weak_ptr;
/// Type of the transport component of the connections that this endpoint
/// creates
@@ -64,7 +64,7 @@ public:
/// Type of a shared pointer to the transport component of the connections
/// that this endpoint creates.
typedef typename transport_con_type::ptr transport_con_ptr;
/// Type of message_handler
typedef typename connection_type::message_handler message_handler;
/// Type of message pointers that this endpoint uses
@@ -73,70 +73,70 @@ public:
/// Type of error logger
typedef typename config::elog_type elog_type;
/// Type of access logger
typedef typename config::alog_type alog_type;
typedef typename config::alog_type alog_type;
/// Type of our concurrency policy's scoped lock object
typedef typename concurrency_type::scoped_lock_type scoped_lock_type;
/// Type of our concurrency policy's mutex object
typedef typename concurrency_type::mutex_type mutex_type;
typedef typename concurrency_type::scoped_lock_type scoped_lock_type;
/// Type of our concurrency policy's mutex object
typedef typename concurrency_type::mutex_type mutex_type;
/// Type of RNG
typedef typename config::rng_type rng_type;
// TODO: organize these
typedef typename connection_type::termination_handler termination_handler;
typedef typename connection_type::termination_handler termination_handler;
typedef lib::shared_ptr<connection_weak_ptr> hdl_type;
explicit endpoint(bool is_server)
: m_alog(config::alog_level,&std::cout)
, m_elog(config::elog_level,&std::cerr)
, m_user_agent(::websocketpp::user_agent)
, m_is_server(is_server)
{
m_alog.set_channels(config::alog_level);
m_elog.set_channels(config::elog_level);
m_alog.write(log::alevel::devel,"endpoint constructor");
explicit endpoint(bool is_server)
: m_alog(config::alog_level,&std::cout)
, m_elog(config::elog_level,&std::cerr)
, m_user_agent(::websocketpp::user_agent)
, m_is_server(is_server)
{
m_alog.set_channels(config::alog_level);
m_elog.set_channels(config::elog_level);
m_alog.write(log::alevel::devel,"endpoint constructor");
transport_type::init_logging(&m_elog,&m_alog);
}
/// Returns the user agent string that this endpoint will use
/**
* Returns the user agent string that this endpoint will use when creating
* new connections.
*
* The default value for this version is WebSocket++/0.3.0dev
*
* @return The user agent string.
*/
std::string get_user_agent() const {
}
/// Returns the user agent string that this endpoint will use
/**
* Returns the user agent string that this endpoint will use when creating
* new connections.
*
* The default value for this version is WebSocket++/0.3.0dev
*
* @return The user agent string.
*/
std::string get_user_agent() const {
scoped_lock_type guard(m_mutex);
return m_user_agent;
}
/// Sets the user agent string that this endpoint will use
/**
* Sets the user agent string that this endpoint will use when creating
* new connections. Changing this value will only affect future connections.
*
* For best results set this before accepting or opening connections.
*
* The default value for this version is WebSocket++/0.3.0dev
*
* @param ua The string to set the user agent to.
*/
void set_user_agent(const std::string& ua) {
return m_user_agent;
}
/// Sets the user agent string that this endpoint will use
/**
* Sets the user agent string that this endpoint will use when creating
* new connections. Changing this value will only affect future connections.
*
* For best results set this before accepting or opening connections.
*
* The default value for this version is WebSocket++/0.3.0dev
*
* @param ua The string to set the user agent to.
*/
void set_user_agent(const std::string& ua) {
scoped_lock_type guard(m_mutex);
m_user_agent = ua;
}
m_user_agent = ua;
}
/// Returns whether or not this endpoint is a server.
/**
* @return Whether or not this endpoint is a server
*/
bool is_server() const {
bool is_server() const {
return m_is_server;
}
@@ -323,15 +323,15 @@ public:
return con;
}
protected:
connection_ptr create_connection();
void remove_connection(connection_ptr con);
connection_ptr create_connection();
void remove_connection(connection_ptr con);
alog_type m_alog;
elog_type m_elog;
private:
// dynamic settings
std::string m_user_agent;
// dynamic settings
std::string m_user_agent;
open_handler m_open_handler;
close_handler m_close_handler;
fail_handler m_fail_handler;
@@ -345,14 +345,14 @@ private:
rng_type m_rng;
// endpoint resources
std::set<connection_ptr> m_connections;
// static settings
const bool m_is_server;
// endpoint state
mutex_type m_mutex;
// endpoint resources
std::set<connection_ptr> m_connections;
// static settings
const bool m_is_server;
// endpoint state
mutex_type m_mutex;
};
} // namespace websocketpp

View File

@@ -105,67 +105,67 @@ enum value {
class category : public lib::error_category {
public:
category() {}
category() {}
const char *name() const _WEBSOCKETPP_NOEXCEPT_TOKEN_ {
return "websocketpp";
}
std::string message(int value) const {
switch(value) {
case error::general:
return "Generic error";
case error::send_queue_full:
return "send queue full";
case error::payload_violation:
return "payload violation";
case error::endpoint_not_secure:
return "endpoint not secure";
case error::endpoint_unavailable:
return "endpoint not available";
case error::invalid_uri:
return "invalid uri";
case error::no_outgoing_buffers:
return "no outgoing message buffers";
case error::no_incoming_buffers:
return "no incoming message buffers";
case error::invalid_state:
return "invalid state";
case error::bad_close_code:
return "Unable to extract close code";
case error::invalid_close_code:
return "Extracted close code is in an invalid range";
case error::reserved_close_code:
return "Extracted close code is in a reserved range";
case error::invalid_utf8:
return "Invalid UTF-8";
case error::invalid_subprotocol:
return "Invalid subprotocol";
case error::bad_connection:
return "Bad Connection";
case error::test:
return "Test Error";
case error::con_creation_failed:
return "Connection creation attempt failed";
case error::unrequested_subprotocol:
return "Selected subprotocol was not requested by the client";
case error::client_only:
return "Feature not available on server endpoints";
case error::server_only:
return "Feature not available on client endpoints";
default:
return "Unknown";
}
}
const char *name() const _WEBSOCKETPP_NOEXCEPT_TOKEN_ {
return "websocketpp";
}
std::string message(int value) const {
switch(value) {
case error::general:
return "Generic error";
case error::send_queue_full:
return "send queue full";
case error::payload_violation:
return "payload violation";
case error::endpoint_not_secure:
return "endpoint not secure";
case error::endpoint_unavailable:
return "endpoint not available";
case error::invalid_uri:
return "invalid uri";
case error::no_outgoing_buffers:
return "no outgoing message buffers";
case error::no_incoming_buffers:
return "no incoming message buffers";
case error::invalid_state:
return "invalid state";
case error::bad_close_code:
return "Unable to extract close code";
case error::invalid_close_code:
return "Extracted close code is in an invalid range";
case error::reserved_close_code:
return "Extracted close code is in a reserved range";
case error::invalid_utf8:
return "Invalid UTF-8";
case error::invalid_subprotocol:
return "Invalid subprotocol";
case error::bad_connection:
return "Bad Connection";
case error::test:
return "Test Error";
case error::con_creation_failed:
return "Connection creation attempt failed";
case error::unrequested_subprotocol:
return "Selected subprotocol was not requested by the client";
case error::client_only:
return "Feature not available on server endpoints";
case error::server_only:
return "Feature not available on client endpoints";
default:
return "Unknown";
}
}
};
inline const lib::error_category& get_category() {
static category instance;
return instance;
static category instance;
return instance;
}
inline lib::error_code make_error_code(error::value e) {
return lib::error_code(static_cast<int>(e), get_category());
return lib::error_code(static_cast<int>(e), get_category());
}
} // namespace error

View File

@@ -47,18 +47,18 @@ static const unsigned int MAX_HEADER_LENGTH = 14;
static const unsigned int MAX_EXTENDED_HEADER_LENGTH = 12;
union uint16_converter {
uint16_t i;
uint8_t c[2];
uint16_t i;
uint8_t c[2];
};
union uint32_converter {
uint32_t i;
uint8_t c[4];
uint32_t i;
uint8_t c[4];
};
union uint64_converter {
uint64_t i;
uint8_t c[8];
uint64_t i;
uint8_t c[8];
};
// WebSocket Opcodes are 4 bits. See spec section 5.2
@@ -115,7 +115,7 @@ namespace opcode {
namespace limits {
/// Maximum size of a basic WebSocket payload
static const uint8_t payload_size_basic = 125;
static const uint8_t payload_size_basic = 125;
/// Maximum size of an extended WebSocket payload (basic payload = 126)
static const uint16_t payload_size_extended = 0xFFFF; // 2^16, 65535
/// Maximum size of a jumbo WebSocket payload (basic payload = 127)
@@ -123,7 +123,7 @@ namespace limits {
/// Maximum size of close frame reason
/// This is payload_size_basic - 2 bytes (as first two bytes are used for
//// the close code
static const uint8_t close_reason_size = 123;
static const uint8_t close_reason_size = 123;
}
@@ -136,97 +136,97 @@ static const uint8_t BHB0_FIN = 0x80;
static const uint8_t BHB1_PAYLOAD = 0x7F;
static const uint8_t BHB1_MASK = 0x80;
static const uint8_t payload_size_code_16bit = 0x7E; // 126
static const uint8_t payload_size_code_64bit = 0x7F; // 127
typedef uint32_converter masking_key_type;
struct basic_header {
basic_header() : b0(0x00),b1(0x00) {}
basic_header(uint8_t p0, uint8_t p1) : b0(p0), b1(p1) {}
basic_header(opcode::value op, uint64_t size, bool fin, bool mask,
bool rsv1 = false, bool rsv2 = false, bool rsv3 = false) : b0(0x00),
b1(0x00)
{
if (fin) {
b0 |= BHB0_FIN;
}
if (rsv1) {
b0 |= BHB0_RSV1;
}
if (rsv2) {
b0 |= BHB0_RSV2;
}
if (rsv3) {
b0 |= BHB0_RSV3;
}
b0 |= (op & BHB0_OPCODE);
if (mask) {
b1 |= BHB1_MASK;
}
uint8_t basic_value;
if (size <= limits::payload_size_basic) {
basic_value = static_cast<uint8_t>(size);
} else if (size <= limits::payload_size_extended) {
basic_value = payload_size_code_16bit;
} else {
basic_value = payload_size_code_64bit;
}
b1 |= basic_value;
}
uint8_t b0;
uint8_t b1;
basic_header() : b0(0x00),b1(0x00) {}
basic_header(uint8_t p0, uint8_t p1) : b0(p0), b1(p1) {}
basic_header(opcode::value op, uint64_t size, bool fin, bool mask,
bool rsv1 = false, bool rsv2 = false, bool rsv3 = false) : b0(0x00),
b1(0x00)
{
if (fin) {
b0 |= BHB0_FIN;
}
if (rsv1) {
b0 |= BHB0_RSV1;
}
if (rsv2) {
b0 |= BHB0_RSV2;
}
if (rsv3) {
b0 |= BHB0_RSV3;
}
b0 |= (op & BHB0_OPCODE);
if (mask) {
b1 |= BHB1_MASK;
}
uint8_t basic_value;
if (size <= limits::payload_size_basic) {
basic_value = static_cast<uint8_t>(size);
} else if (size <= limits::payload_size_extended) {
basic_value = payload_size_code_16bit;
} else {
basic_value = payload_size_code_64bit;
}
b1 |= basic_value;
}
uint8_t b0;
uint8_t b1;
};
struct extended_header {
extended_header() {
std::fill_n(this->bytes,MAX_EXTENDED_HEADER_LENGTH,0x00);
}
extended_header(uint64_t payload_size) {
std::fill_n(this->bytes,MAX_EXTENDED_HEADER_LENGTH,0x00);
copy_payload(payload_size);
}
extended_header(uint64_t payload_size, uint32_t masking_key) {
std::fill_n(this->bytes,MAX_EXTENDED_HEADER_LENGTH,0x00);
// Copy payload size
int offset = copy_payload(payload_size);
// Copy Masking Key
uint32_converter temp32;
temp32.i = masking_key;
std::copy(temp32.c,temp32.c+4,bytes+offset);
}
extended_header() {
std::fill_n(this->bytes,MAX_EXTENDED_HEADER_LENGTH,0x00);
}
extended_header(uint64_t payload_size) {
std::fill_n(this->bytes,MAX_EXTENDED_HEADER_LENGTH,0x00);
copy_payload(payload_size);
}
extended_header(uint64_t payload_size, uint32_t masking_key) {
std::fill_n(this->bytes,MAX_EXTENDED_HEADER_LENGTH,0x00);
// Copy payload size
int offset = copy_payload(payload_size);
// Copy Masking Key
uint32_converter temp32;
temp32.i = masking_key;
std::copy(temp32.c,temp32.c+4,bytes+offset);
}
uint8_t bytes[MAX_EXTENDED_HEADER_LENGTH];
uint8_t bytes[MAX_EXTENDED_HEADER_LENGTH];
private:
int copy_payload(uint64_t payload_size) {
int payload_offset = 0;
if (payload_size <= limits::payload_size_basic) {
payload_offset = 8;
} else if (payload_size <= limits::payload_size_extended) {
payload_offset = 6;
}
uint64_converter temp64;
temp64.i = lib::net::htonll(payload_size);
std::copy(temp64.c+payload_offset,temp64.c+8,bytes);
return 8-payload_offset;
}
int copy_payload(uint64_t payload_size) {
int payload_offset = 0;
if (payload_size <= limits::payload_size_basic) {
payload_offset = 8;
} else if (payload_size <= limits::payload_size_extended) {
payload_offset = 6;
}
uint64_converter temp64;
temp64.i = lib::net::htonll(payload_size);
std::copy(temp64.c+payload_offset,temp64.c+8,bytes);
return 8-payload_offset;
}
};
// Forward function declarations
@@ -256,12 +256,12 @@ void byte_mask(iter_type b, iter_type e, iter_type o, const masking_key_type&
key, size_t key_offset = 0);
template <typename iter_type>
void byte_mask(iter_type b, iter_type e, const masking_key_type& key,
size_t key_offset = 0);
size_t key_offset = 0);
void word_mask_exact(uint8_t* input, uint8_t* output, size_t length,
const masking_key_type& key);
const masking_key_type& key);
void word_mask_exact(uint8_t* data, size_t length, const masking_key_type& key);
size_t word_mask_circ(uint8_t* input, uint8_t* output, size_t length,
size_t prepared_key);
size_t prepared_key);
size_t word_mask_circ(uint8_t* data, size_t length, size_t prepared_key);
@@ -272,7 +272,7 @@ size_t word_mask_circ(uint8_t* data, size_t length, size_t prepared_key);
* @return True if the header's fin bit is set.
*/
inline bool get_fin(const basic_header &h) {
return ((h.b0 & BHB0_FIN) == BHB0_FIN);
return ((h.b0 & BHB0_FIN) == BHB0_FIN);
}
/// Set the frame's FIN bit
@@ -282,7 +282,7 @@ inline bool get_fin(const basic_header &h) {
* @param value Value to set it to
*/
inline void set_fin(basic_header &h, bool value) {
h.b0 = (value ? h.b0 | BHB0_FIN : h.b0 & ~BHB0_FIN);
h.b0 = (value ? h.b0 | BHB0_FIN : h.b0 & ~BHB0_FIN);
}
/// check whether the frame's RSV1 bit is set
@@ -290,7 +290,7 @@ inline void set_fin(basic_header &h, bool value) {
* @return True if the header's RSV1 bit is set.
*/
inline bool get_rsv1(const basic_header &h) {
return ((h.b0 & BHB0_RSV1) == BHB0_RSV1);
return ((h.b0 & BHB0_RSV1) == BHB0_RSV1);
}
/// Set the frame's RSV1 bit
@@ -300,7 +300,7 @@ inline bool get_rsv1(const basic_header &h) {
* @param value Value to set it to
*/
inline void set_rsv1(basic_header &h, bool value) {
h.b0 = (value ? h.b0 | BHB0_RSV1 : h.b0 & ~BHB0_RSV1);
h.b0 = (value ? h.b0 | BHB0_RSV1 : h.b0 & ~BHB0_RSV1);
}
/// check whether the frame's RSV2 bit is set
@@ -308,7 +308,7 @@ inline void set_rsv1(basic_header &h, bool value) {
* @return True if the header's RSV2 bit is set.
*/
inline bool get_rsv2(const basic_header &h) {
return ((h.b0 & BHB0_RSV2) == BHB0_RSV2);
return ((h.b0 & BHB0_RSV2) == BHB0_RSV2);
}
/// Set the frame's RSV2 bit
@@ -318,7 +318,7 @@ inline bool get_rsv2(const basic_header &h) {
* @param value Value to set it to
*/
inline void set_rsv2(basic_header &h, bool value) {
h.b0 = (value ? h.b0 | BHB0_RSV2 : h.b0 & ~BHB0_RSV2);
h.b0 = (value ? h.b0 | BHB0_RSV2 : h.b0 & ~BHB0_RSV2);
}
/// check whether the frame's RSV3 bit is set
@@ -326,7 +326,7 @@ inline void set_rsv2(basic_header &h, bool value) {
* @return True if the header's RSV3 bit is set.
*/
inline bool get_rsv3(const basic_header &h) {
return ((h.b0 & BHB0_RSV3) == BHB0_RSV3);
return ((h.b0 & BHB0_RSV3) == BHB0_RSV3);
}
/// Set the frame's RSV3 bit
@@ -336,12 +336,12 @@ inline bool get_rsv3(const basic_header &h) {
* @param value Value to set it to
*/
inline void set_rsv3(basic_header &h, bool value) {
h.b0 = (value ? h.b0 | BHB0_RSV3 : h.b0 & ~BHB0_RSV3);
h.b0 = (value ? h.b0 | BHB0_RSV3 : h.b0 & ~BHB0_RSV3);
}
/// Extract opcode from basic header
inline opcode::value get_opcode(const basic_header &h) {
return opcode::value(h.b0 & BHB0_OPCODE);
return opcode::value(h.b0 & BHB0_OPCODE);
}
/// check whether the frame is masked
@@ -349,7 +349,7 @@ inline opcode::value get_opcode(const basic_header &h) {
* @return True if the header mask bit is set.
*/
inline bool get_masked(const basic_header &h) {
return ((h.b1 & BHB1_MASK) == BHB1_MASK);
return ((h.b1 & BHB1_MASK) == BHB1_MASK);
}
/// Set the frame's MASK bit
@@ -359,7 +359,7 @@ inline bool get_masked(const basic_header &h) {
* @param value Value to set it to
*/
inline void set_masked(basic_header &h, bool value) {
h.b1 = (value ? h.b1 | BHB1_MASK : h.b1 & ~BHB1_MASK);
h.b1 = (value ? h.b1 | BHB1_MASK : h.b1 & ~BHB1_MASK);
}
/// Extracts the raw payload length specified in the basic header
@@ -380,7 +380,7 @@ inline void set_masked(basic_header &h, bool value) {
* @return the exact size encoded in h
*/
inline uint8_t get_basic_size(const basic_header &h) {
return h.b1 & BHB1_PAYLOAD;
return h.b1 & BHB1_PAYLOAD;
}
/// Set the frame's MASK bit
@@ -392,23 +392,23 @@ inline uint8_t get_basic_size(const basic_header &h) {
inline lib::error_code set_size(basic_header &h, extended_header &eh, uint64_t
size)
{
// make sure value isn't too big
uint8_t basic_value;
if (size <= limits::payload_size_basic) {
basic_value = static_cast<uint8_t>(size);
} else if (size <= limits::payload_size_extended) {
basic_value = payload_size_code_16bit;
} else if (size <= limits::payload_size_jumbo) {
basic_value = payload_size_code_64bit;
} else {
// error
return lib::error_code();
}
h.b1 = (basic_value & BHB1_PAYLOAD) | (h.b1 & BHB1_MASK);
return lib::error_code();
// make sure value isn't too big
uint8_t basic_value;
if (size <= limits::payload_size_basic) {
basic_value = static_cast<uint8_t>(size);
} else if (size <= limits::payload_size_extended) {
basic_value = payload_size_code_16bit;
} else if (size <= limits::payload_size_jumbo) {
basic_value = payload_size_code_64bit;
} else {
// error
return lib::error_code();
}
h.b1 = (basic_value & BHB1_PAYLOAD) | (h.b1 & BHB1_MASK);
return lib::error_code();
}
/// Calculates the full length of the header based on the first bytes.
@@ -423,18 +423,18 @@ inline lib::error_code set_size(basic_header &h, extended_header &eh, uint64_t
* @return Full length of the extended header.
*/
inline size_t get_header_len(const basic_header &h) {
// TODO: check extensions?
// masking key offset represents the space used for the extended length
// fields
size_t size = BASIC_HEADER_LENGTH + get_masking_key_offset(h);
// If the header is masked there is a 4 byte masking key
if (get_masked(h)) {
size += 4;
}
return size;
// TODO: check extensions?
// masking key offset represents the space used for the extended length
// fields
size_t size = BASIC_HEADER_LENGTH + get_masking_key_offset(h);
// If the header is masked there is a 4 byte masking key
if (get_masked(h)) {
size += 4;
}
return size;
}
/// Calculate the offset location of the masking key within the extended header
@@ -447,13 +447,13 @@ inline size_t get_header_len(const basic_header &h) {
* @return byte offset of the first byte of the masking key
*/
inline unsigned int get_masking_key_offset(const basic_header &h) {
if (get_basic_size(h) == payload_size_code_16bit) {
return 2;
} else if (get_basic_size(h) == payload_size_code_64bit) {
return 8;
} else {
return 0;
}
if (get_basic_size(h) == payload_size_code_16bit) {
return 2;
} else if (get_basic_size(h) == payload_size_code_64bit) {
return 8;
} else {
return 0;
}
}
/// Generate a properly sized contiguous string that encodes a full frame header
@@ -469,16 +469,16 @@ inline unsigned int get_masking_key_offset(const basic_header &h) {
inline std::string prepare_header(const basic_header &h, const
extended_header &e)
{
std::string ret;
ret.push_back(char(h.b0));
ret.push_back(char(h.b1));
ret.append(
reinterpret_cast<const char*>(e.bytes),
get_header_len(h)-BASIC_HEADER_LENGTH
);
return ret;
std::string ret;
ret.push_back(char(h.b0));
ret.push_back(char(h.b1));
ret.append(
reinterpret_cast<const char*>(e.bytes),
get_header_len(h)-BASIC_HEADER_LENGTH
);
return ret;
}
/// Extract the masking key from a frame header
@@ -496,16 +496,16 @@ inline std::string prepare_header(const basic_header &h, const
inline masking_key_type get_masking_key(const basic_header &h, const
extended_header &e)
{
masking_key_type temp32;
masking_key_type temp32;
if (!get_masked(h)) {
temp32.i = 0;
} else {
unsigned int offset = get_masking_key_offset(h);
std::copy(e.bytes+offset,e.bytes+offset+4,temp32.c);
}
if (!get_masked(h)) {
temp32.i = 0;
} else {
unsigned int offset = get_masking_key_offset(h);
std::copy(e.bytes+offset,e.bytes+offset+4,temp32.c);
}
return temp32;
return temp32;
}
/// Extract the extended size field from an extended header
@@ -518,9 +518,9 @@ inline masking_key_type get_masking_key(const basic_header &h, const
* @return The size encoded in the extended header in host byte order
*/
inline uint16_t get_extended_size(const extended_header &e) {
uint16_converter temp16;
std::copy(e.bytes,e.bytes+2,temp16.c);
return ntohs(temp16.i);
uint16_converter temp16;
std::copy(e.bytes,e.bytes+2,temp16.c);
return ntohs(temp16.i);
}
/// Extract the jumbo size field from an extended header
@@ -533,9 +533,9 @@ inline uint16_t get_extended_size(const extended_header &e) {
* @return The size encoded in the extended header in host byte order
*/
inline uint64_t get_jumbo_size(const extended_header &e) {
uint64_converter temp64;
std::copy(e.bytes,e.bytes+8,temp64.c);
return lib::net::ntohll(temp64.i);
uint64_converter temp64;
std::copy(e.bytes,e.bytes+8,temp64.c);
return lib::net::ntohll(temp64.i);
}
/// Extract the full payload size field from a WebSocket header
@@ -553,15 +553,15 @@ inline uint64_t get_jumbo_size(const extended_header &e) {
inline uint64_t get_payload_size(const basic_header &h, const
extended_header &e)
{
uint8_t val = get_basic_size(h);
uint8_t val = get_basic_size(h);
if (val <= limits::payload_size_basic) {
return val;
} else if (val == payload_size_code_16bit) {
return get_extended_size(e);
} else {
return get_jumbo_size(e);
}
if (val <= limits::payload_size_basic) {
return val;
} else if (val == payload_size_code_16bit) {
return get_extended_size(e);
} else {
return get_jumbo_size(e);
}
}
/// Extract a masking key into a value the size of a machine word.
@@ -573,14 +573,14 @@ inline uint64_t get_payload_size(const basic_header &h, const
* @return prepared key as a machine word
*/
inline size_t prepare_masking_key(const masking_key_type& key) {
size_t low_bits = static_cast<size_t>(key.i);
if (sizeof(size_t) == 8) {
uint64_t high_bits = static_cast<size_t>(key.i);
return static_cast<size_t>((high_bits << 32) | low_bits);
} else {
return low_bits;
}
size_t low_bits = static_cast<size_t>(key.i);
if (sizeof(size_t) == 8) {
uint64_t high_bits = static_cast<size_t>(key.i);
return static_cast<size_t>((high_bits << 32) | low_bits);
} else {
return low_bits;
}
}
/// circularly shifts the supplied prepared masking key by offset bytes
@@ -648,7 +648,7 @@ void byte_mask(iter_type b, iter_type e, iter_type o, const masking_key_type&
*/
template <typename iter_type>
void byte_mask(iter_type b, iter_type e, const masking_key_type& key,
size_t key_offset)
size_t key_offset)
{
byte_mask(b,e,b,key,key_offset);
}
@@ -675,7 +675,7 @@ void byte_mask(iter_type b, iter_type e, const masking_key_type& key,
* @param key Masking key to use
*/
inline void word_mask_exact(uint8_t* input, uint8_t* output, size_t length,
const masking_key_type& key)
const masking_key_type& key)
{
size_t prepared_key = prepare_masking_key(key);
size_t n = length/sizeof(size_t);
@@ -741,26 +741,26 @@ inline void word_mask_exact(uint8_t* data, size_t length, const
* @return the prepared_key shifted to account for the input length
*/
inline size_t word_mask_circ(uint8_t * input, uint8_t * output, size_t length,
size_t prepared_key)
size_t prepared_key)
{
size_t n = length / sizeof(size_t); // whole words
size_t l = length - (n * sizeof(size_t)); // remaining bytes
size_t l = length - (n * sizeof(size_t)); // remaining bytes
size_t * input_word = reinterpret_cast<size_t *>(input);
size_t * output_word = reinterpret_cast<size_t *>(output);
// mask word by word
// mask word by word
for (size_t i = 0; i < n; i++) {
output_word[i] = input_word[i] ^ prepared_key;
}
// mask partial word at the end
// mask partial word at the end
size_t start = length - l;
uint8_t * byte_key = reinterpret_cast<uint8_t *>(&prepared_key);
for (size_t i = 0; i < l; ++i) {
output[start+i] = input[start+i] ^ byte_key[i];
}
return circshift_prepared_key(prepared_key,l);
return circshift_prepared_key(prepared_key,l);
}
/// Circular word aligned mask/unmask (in place)
@@ -778,7 +778,7 @@ inline size_t word_mask_circ(uint8_t * input, uint8_t * output, size_t length,
* @return the prepared_key shifted to account for the input length
*/
inline size_t word_mask_circ(uint8_t* data, size_t length, size_t prepared_key){
return word_mask_circ(data,data,length,prepared_key);
return word_mask_circ(data,data,length,prepared_key);
}
} // namespace frame

View File

@@ -46,39 +46,39 @@ namespace http {
// 0x00 - 0x32, 0x7f-0xff
// ( ) < > @ , ; : \ " / [ ] ? = { }
static const char header_token[] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 00..0f
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 10..1f
0,1,0,1,1,1,1,1,0,0,1,1,0,1,1,0, // 20..2f
1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0, // 30..3f
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 40..4f
1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1, // 50..5f
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 60..6f
1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,0, // 70..7f
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 80..8f
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 90..9f
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // a0..af
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // b0..bf
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // c0..cf
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // d0..df
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // e0..ef
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // f0..ff
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 00..0f
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 10..1f
0,1,0,1,1,1,1,1,0,0,1,1,0,1,1,0, // 20..2f
1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0, // 30..3f
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 40..4f
1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1, // 50..5f
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 60..6f
1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,0, // 70..7f
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 80..8f
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 90..9f
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // a0..af
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // b0..bf
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // c0..cf
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // d0..df
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // e0..ef
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // f0..ff
};
inline bool is_token_char(unsigned char c) {
return (header_token[c] == 1);
return (header_token[c] == 1);
}
inline bool is_not_token_char(unsigned char c) {
return !header_token[c];
return !header_token[c];
}
// Space (32) or horizontal tab (9)
inline bool is_whitespace_char(unsigned char c) {
return (c == 9 || c == 32);
return (c == 9 || c == 32);
}
inline bool is_not_whitespace_char(unsigned char c) {
return (c != 9 && c != 32);
return (c != 9 && c != 32);
}
namespace status_code {
@@ -142,7 +142,7 @@ namespace http {
inline std::string get_string(value c) {
switch (c) {
case uninitialized:
return "Uninitialized";
return "Uninitialized";
case continue_code:
return "Continue";
case switching_protocols:
@@ -180,7 +180,7 @@ namespace http {
case unauthorized:
return "Unauthorized";
case payment_required:
return "Payment Required";
return "Payment Required";
case forbidden:
return "Forbidden";
case not_found:

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, Peter Thorson. All rights reserved.
* Copyright (c) 2013, 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:
@@ -109,16 +109,16 @@ inline void parser::remove_header(const std::string &key) {
}
inline void parser::set_body(const std::string& value) {
if (value.size() == 0) {
remove_header("Content-Length");
m_body = "";
return;
}
std::stringstream foo;
foo << value.size();
replace_header("Content-Length", foo.str());
m_body = value;
if (value.size() == 0) {
remove_header("Content-Length");
m_body = "";
return;
}
std::stringstream foo;
foo << value.size();
replace_header("Content-Length", foo.str());
m_body = value;
}
inline bool parser::parse_headers(std::istream& s) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, Peter Thorson. All rights reserved.
* Copyright (c) 2013, 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:
@@ -38,143 +38,143 @@ namespace http {
namespace parser {
inline bool request::parse_complete(std::istream& s) {
std::string request;
// get status line
std::getline(s, request);
if (request[request.size()-1] == '\r') {
request.erase(request.end()-1);
std::stringstream ss(request);
std::string val;
ss >> val;
set_method(val);
ss >> val;
set_uri(val);
ss >> val;
set_version(val);
} else {
return false;
}
return parse_headers(s);
std::string request;
// get status line
std::getline(s, request);
if (request[request.size()-1] == '\r') {
request.erase(request.end()-1);
std::stringstream ss(request);
std::string val;
ss >> val;
set_method(val);
ss >> val;
set_uri(val);
ss >> val;
set_version(val);
} else {
return false;
}
return parse_headers(s);
}
inline size_t request::consume(const char *buf, size_t len) {
if (m_ready) {return 0;}
if (m_buf->size() + len > max_header_size) {
// exceeded max header size
throw exception("Maximum header size exceeded.",
status_code::request_header_fields_too_large);
}
// copy new header bytes into buffer
m_buf->append(buf,len);
// Search for delimiter in buf. If found read until then. If not read all
std::string::iterator begin = m_buf->begin();
std::string::iterator end;
for (;;) {
// search for line delimiter
end = std::search(
begin,
m_buf->end(),
header_delimiter,
header_delimiter+sizeof(header_delimiter)-1
);
//std::cout << "mark5: " << end-begin << std::endl;
//std::cout << "mark6: " << sizeof(header_delimiter) << std::endl;
if (m_ready) {return 0;}
if (m_buf->size() + len > max_header_size) {
// exceeded max header size
throw exception("Maximum header size exceeded.",
status_code::request_header_fields_too_large);
}
// copy new header bytes into buffer
m_buf->append(buf,len);
// Search for delimiter in buf. If found read until then. If not read all
std::string::iterator begin = m_buf->begin();
std::string::iterator end;
for (;;) {
// search for line delimiter
end = std::search(
begin,
m_buf->end(),
header_delimiter,
header_delimiter+sizeof(header_delimiter)-1
);
//std::cout << "mark5: " << end-begin << std::endl;
//std::cout << "mark6: " << sizeof(header_delimiter) << std::endl;
if (end == m_buf->end()) {
// we are out of bytes. Discard the processed bytes and copy the
// remaining unprecessed bytes to the beginning of the buffer
std::copy(begin,end,m_buf->begin());
m_buf->resize(static_cast<std::string::size_type>(end-begin));
return len;
}
//the range [begin,end) now represents a line to be processed.
if (end-begin == 0) {
// we got a blank line
if (m_method.empty() || get_header("Host") == "") {
throw exception("Incomplete Request",status_code::bad_request);
}
m_ready = true;
size_t bytes_processed = (
len - static_cast<std::string::size_type>(m_buf->end()-end)
+ sizeof(header_delimiter) - 1
);
// frees memory used temporarily during request parsing
m_buf.reset();
// return number of bytes processed (starting bytes - bytes left)
return bytes_processed;
} else {
if (m_method.empty()) {
this->process(begin,end);
} else {
this->process_header(begin,end);
}
}
begin = end+sizeof(header_delimiter)-1;
}
if (end == m_buf->end()) {
// we are out of bytes. Discard the processed bytes and copy the
// remaining unprecessed bytes to the beginning of the buffer
std::copy(begin,end,m_buf->begin());
m_buf->resize(static_cast<std::string::size_type>(end-begin));
return len;
}
//the range [begin,end) now represents a line to be processed.
if (end-begin == 0) {
// we got a blank line
if (m_method.empty() || get_header("Host") == "") {
throw exception("Incomplete Request",status_code::bad_request);
}
m_ready = true;
size_t bytes_processed = (
len - static_cast<std::string::size_type>(m_buf->end()-end)
+ sizeof(header_delimiter) - 1
);
// frees memory used temporarily during request parsing
m_buf.reset();
// return number of bytes processed (starting bytes - bytes left)
return bytes_processed;
} else {
if (m_method.empty()) {
this->process(begin,end);
} else {
this->process_header(begin,end);
}
}
begin = end+sizeof(header_delimiter)-1;
}
}
inline std::string request::raw() {
// TODO: validation. Make sure all required fields have been set?
std::stringstream raw;
raw << m_method << " " << m_uri << " " << get_version() << "\r\n";
raw << raw_headers() << "\r\n" << m_body;
return raw.str();
// TODO: validation. Make sure all required fields have been set?
std::stringstream raw;
raw << m_method << " " << m_uri << " " << get_version() << "\r\n";
raw << raw_headers() << "\r\n" << m_body;
return raw.str();
}
inline void request::set_method(const std::string& method) {
if (std::find_if(method.begin(),method.end(),is_not_token_char) != method.end()) {
throw exception("Invalid method token.",status_code::bad_request);
}
if (std::find_if(method.begin(),method.end(),is_not_token_char) != method.end()) {
throw exception("Invalid method token.",status_code::bad_request);
}
m_method = method;
m_method = method;
}
inline void request::set_uri(const std::string& uri) {
// TODO: validation?
m_uri = uri;
// TODO: validation?
m_uri = uri;
}
inline void request::process(std::string::iterator begin, std::string::iterator
end)
{
std::string::iterator cursor_start = begin;
std::string::iterator cursor_end = std::find(begin,end,' ');
if (cursor_end == end) {
throw exception("Invalid request line1",status_code::bad_request);
}
set_method(std::string(cursor_start,cursor_end));
cursor_start = cursor_end+1;
cursor_end = std::find(cursor_start,end,' ');
if (cursor_end == end) {
throw exception("Invalid request line2",status_code::bad_request);
}
set_uri(std::string(cursor_start,cursor_end));
set_version(std::string(cursor_end+1,end));
std::string::iterator cursor_start = begin;
std::string::iterator cursor_end = std::find(begin,end,' ');
if (cursor_end == end) {
throw exception("Invalid request line1",status_code::bad_request);
}
set_method(std::string(cursor_start,cursor_end));
cursor_start = cursor_end+1;
cursor_end = std::find(cursor_start,end,' ');
if (cursor_end == end) {
throw exception("Invalid request line2",status_code::bad_request);
}
set_uri(std::string(cursor_start,cursor_end));
set_version(std::string(cursor_end+1,end));
}
} // namespace parser

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, Peter Thorson. All rights reserved.
* Copyright (c) 2013, 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:
@@ -38,97 +38,97 @@ namespace http {
namespace parser {
inline size_t response::consume(const char *buf, size_t len) {
if (m_state == DONE) {return 0;}
if (m_state == BODY) {
return this->process_body(buf,len);
}
if (m_read + len > max_header_size) {
// exceeded max header size
throw exception("Maximum header size exceeded.",
status_code::request_header_fields_too_large);
}
// copy new header bytes into buffer
m_buf->append(buf,len);
// Search for delimiter in buf. If found read until then. If not read all
std::string::iterator begin = m_buf->begin();
std::string::iterator end = begin;
for (;;) {
// search for delimiter
end = std::search(
begin,
m_buf->end(),
header_delimiter,
header_delimiter + sizeof(header_delimiter) - 1
);
if (end == m_buf->end()) {
// we are out of bytes. Discard the processed bytes and copy the
// remaining unprecessed bytes to the beginning of the buffer
std::copy(begin,end,m_buf->begin());
m_buf->resize(static_cast<std::string::size_type>(end-begin));
m_read +=len;
return len;
}
//the range [begin,end) now represents a line to be processed.
if (end-begin == 0) {
// we got a blank line
if (m_state == RESPONSE_LINE) {
throw exception("Incomplete Request",status_code::bad_request);
}
// TODO: grab content-length
std::string length = get_header("Content-Length");
if (length == "") {
// no content length found, read indefinitely
m_read = 0;
} else {
std::istringstream ss(length);
if ((ss >> m_read).fail()) {
throw exception("Unable to parse Content-Length header",
status_code::bad_request);
}
}
m_state = BODY;
// calc header bytes processed (starting bytes - bytes left)
size_t read = (
len - static_cast<std::string::size_type>(m_buf->end() - end)
+ sizeof(header_delimiter) - 1
);
// if there were bytes left process them as body bytes
if (read < len) {
read += this->process_body(buf+read,(len-read));
}
// frees memory used temporarily during header parsing
m_buf.reset();
return read;
} else {
if (m_state == RESPONSE_LINE) {
this->process(begin,end);
m_state = HEADERS;
} else {
this->process_header(begin,end);
}
}
begin = end+sizeof(header_delimiter) - 1;
}
if (m_state == DONE) {return 0;}
if (m_state == BODY) {
return this->process_body(buf,len);
}
if (m_read + len > max_header_size) {
// exceeded max header size
throw exception("Maximum header size exceeded.",
status_code::request_header_fields_too_large);
}
// copy new header bytes into buffer
m_buf->append(buf,len);
// Search for delimiter in buf. If found read until then. If not read all
std::string::iterator begin = m_buf->begin();
std::string::iterator end = begin;
for (;;) {
// search for delimiter
end = std::search(
begin,
m_buf->end(),
header_delimiter,
header_delimiter + sizeof(header_delimiter) - 1
);
if (end == m_buf->end()) {
// we are out of bytes. Discard the processed bytes and copy the
// remaining unprecessed bytes to the beginning of the buffer
std::copy(begin,end,m_buf->begin());
m_buf->resize(static_cast<std::string::size_type>(end-begin));
m_read +=len;
return len;
}
//the range [begin,end) now represents a line to be processed.
if (end-begin == 0) {
// we got a blank line
if (m_state == RESPONSE_LINE) {
throw exception("Incomplete Request",status_code::bad_request);
}
// TODO: grab content-length
std::string length = get_header("Content-Length");
if (length == "") {
// no content length found, read indefinitely
m_read = 0;
} else {
std::istringstream ss(length);
if ((ss >> m_read).fail()) {
throw exception("Unable to parse Content-Length header",
status_code::bad_request);
}
}
m_state = BODY;
// calc header bytes processed (starting bytes - bytes left)
size_t read = (
len - static_cast<std::string::size_type>(m_buf->end() - end)
+ sizeof(header_delimiter) - 1
);
// if there were bytes left process them as body bytes
if (read < len) {
read += this->process_body(buf+read,(len-read));
}
// frees memory used temporarily during header parsing
m_buf.reset();
return read;
} else {
if (m_state == RESPONSE_LINE) {
this->process(begin,end);
m_state = HEADERS;
} else {
this->process_header(begin,end);
}
}
begin = end+sizeof(header_delimiter) - 1;
}
}
inline size_t response::consume(std::istream & s) {
@@ -171,115 +171,115 @@ inline size_t response::consume(std::istream & s) {
}
inline bool response::parse_complete(std::istream& s) {
// parse a complete header (ie \r\n\r\n MUST be in the input stream)
std::string response;
// get status line
std::getline(s, response);
if (response[response.size()-1] == '\r') {
response.erase(response.end()-1);
std::stringstream ss(response);
std::string str_val;
int int_val;
char char_val[256];
ss >> str_val;
set_version(str_val);
ss >> int_val;
ss.getline(char_val,256);
set_status(status_code::value(int_val),std::string(char_val));
} else {
return false;
}
return parse_headers(s);
// parse a complete header (ie \r\n\r\n MUST be in the input stream)
std::string response;
// get status line
std::getline(s, response);
if (response[response.size()-1] == '\r') {
response.erase(response.end()-1);
std::stringstream ss(response);
std::string str_val;
int int_val;
char char_val[256];
ss >> str_val;
set_version(str_val);
ss >> int_val;
ss.getline(char_val,256);
set_status(status_code::value(int_val),std::string(char_val));
} else {
return false;
}
return parse_headers(s);
}
inline std::string response::raw() const {
// TODO: validation. Make sure all required fields have been set?
std::stringstream raw;
raw << get_version() << " " << m_status_code << " " << m_status_msg;
raw << "\r\n" << raw_headers() << "\r\n";
raw << m_body;
return raw.str();
// TODO: validation. Make sure all required fields have been set?
std::stringstream raw;
raw << get_version() << " " << m_status_code << " " << m_status_msg;
raw << "\r\n" << raw_headers() << "\r\n";
raw << m_body;
return raw.str();
}
inline void response::set_status(status_code::value code) {
// TODO: validation?
m_status_code = code;
m_status_msg = get_string(code);
// TODO: validation?
m_status_code = code;
m_status_msg = get_string(code);
}
inline void response::set_status(status_code::value code, const std::string&
msg)
{
// TODO: validation?
m_status_code = code;
m_status_msg = msg;
// TODO: validation?
m_status_code = code;
m_status_msg = msg;
}
inline void response::process(std::string::iterator begin,
std::string::iterator end)
{
std::string::iterator cursor_start = begin;
std::string::iterator cursor_end = std::find(begin,end,' ');
if (cursor_end == end) {
throw exception("Invalid response line",status_code::bad_request);
}
set_version(std::string(cursor_start,cursor_end));
cursor_start = cursor_end+1;
cursor_end = std::find(cursor_start,end,' ');
if (cursor_end == end) {
throw exception("Invalid request line",status_code::bad_request);
}
int code;
std::istringstream ss(std::string(cursor_start,cursor_end));
if ((ss >> code).fail()) {
throw exception("Unable to parse response code",status_code::bad_request);
}
set_status(status_code::value(code),std::string(cursor_end+1,end));
std::string::iterator cursor_start = begin;
std::string::iterator cursor_end = std::find(begin,end,' ');
if (cursor_end == end) {
throw exception("Invalid response line",status_code::bad_request);
}
set_version(std::string(cursor_start,cursor_end));
cursor_start = cursor_end+1;
cursor_end = std::find(cursor_start,end,' ');
if (cursor_end == end) {
throw exception("Invalid request line",status_code::bad_request);
}
int code;
std::istringstream ss(std::string(cursor_start,cursor_end));
if ((ss >> code).fail()) {
throw exception("Unable to parse response code",status_code::bad_request);
}
set_status(status_code::value(code),std::string(cursor_end+1,end));
}
inline size_t response::process_body(const char *buf, size_t len) {
// If no content length was set then we read forever and never set m_ready
if (m_read == 0) {
//m_body.append(buf,len);
//return len;
m_state = DONE;
return 0;
}
// Otherwise m_read is the number of bytes left.
size_t to_read;
if (len >= m_read) {
// if we have more bytes than we need read, read only the amount needed
// then set done state
to_read = m_read;
m_state = DONE;
} else {
// we need more bytes than are avaliable, read them all
to_read = len;
}
m_body.append(buf,to_read);
m_read -= to_read;
return to_read;
// If no content length was set then we read forever and never set m_ready
if (m_read == 0) {
//m_body.append(buf,len);
//return len;
m_state = DONE;
return 0;
}
// Otherwise m_read is the number of bytes left.
size_t to_read;
if (len >= m_read) {
// if we have more bytes than we need read, read only the amount needed
// then set done state
to_read = m_read;
m_state = DONE;
} else {
// we need more bytes than are avaliable, read them all
to_read = len;
}
m_body.append(buf,to_read);
m_read -= to_read;
return to_read;
}
} // namespace parser

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, Peter Thorson. All rights reserved.
* Copyright (c) 2013, 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:
@@ -39,12 +39,12 @@ namespace http {
namespace parser {
namespace state {
enum value {
method,
resource,
version,
headers
};
enum value {
method,
resource,
version,
headers
};
}
typedef std::map<std::string,std::string> header_list;
@@ -142,7 +142,7 @@ struct attribute {
typedef std::vector<attribute> attribute_list;
struct parameter {
parameter(std::string n) : name(n) {}
parameter(std::string n) : name(n) {}
void add_attribute(const attribute& p) {
attributes.push_back(p);
@@ -353,7 +353,7 @@ public:
/// Get the HTTP version string
const std::string& get_version() const {
return m_version;
return m_version;
}
/// Get the HTTP header with name `key`
@@ -365,7 +365,7 @@ public:
/// Get the body string
const std::string& get_body() const {
return m_body;
return m_body;
}
/// Get the HTTP header with name `key`
@@ -417,7 +417,7 @@ public:
*/
void set_body(const std::string& value);
protected:
/// DEPRECATED Read headers out of an istream
/// DEPRECATED Read headers out of an istream
bool parse_headers(std::istream& s);
/// Helper function for consume. Process header line

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, Peter Thorson. All rights reserved.
* Copyright (c) 2013, 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:
@@ -84,7 +84,7 @@ public:
/// Returns whether or not the request is ready for reading.
bool ready() const {
return m_ready;
return m_ready;
}
/// Returns the full raw request
@@ -95,7 +95,7 @@ public:
/// Return the request method
const std::string& get_method() const {
return m_method;
return m_method;
}
/// Set the HTTP uri. Must be a valid HTTP uri
@@ -103,17 +103,17 @@ public:
/// Return the requested URI
const std::string& get_uri() const {
return m_uri;
return m_uri;
}
private:
/// Helper function for message::consume. Process request line
void process(std::string::iterator begin, std::string::iterator end);
lib::shared_ptr<std::string> m_buf;
std::string m_method;
std::string m_uri;
bool m_ready;
/// Helper function for message::consume. Process request line
void process(std::string::iterator begin, std::string::iterator end);
lib::shared_ptr<std::string> m_buf;
std::string m_method;
std::string m_uri;
bool m_ready;
};
} // namespace parser

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, Peter Thorson. All rights reserved.
* Copyright (c) 2013, 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:
@@ -53,16 +53,16 @@ namespace parser {
*/
class response : public parser {
public:
typedef response type;
typedef response type;
typedef lib::shared_ptr<type> ptr;
response()
response()
: m_read(0)
, m_buf(new std::string())
, m_status_code(status_code::uninitialized)
, m_state(RESPONSE_LINE) {}
/// Process bytes in the input buffer
/// Process bytes in the input buffer
/**
* Process up to len bytes from input buffer buf. Returns the number of
* bytes processed. Bytes left unprocessed means bytes left over after the
@@ -91,12 +91,12 @@ public:
* @note will never return true if the content length header is not present
*/
bool ready() const {
return m_state == DONE;
return m_state == DONE;
}
/// Returns true if the response headers are fully parsed.
bool headers_ready() const {
return (m_state == BODY || m_state == DONE);
return (m_state == BODY || m_state == DONE);
}
/// DEPRECATED parse a complete response from a pre-delimited istream
@@ -130,32 +130,32 @@ public:
/// Return the response status code
status_code::value get_status_code() const {
return m_status_code;
return m_status_code;
}
/// Return the response status message
const std::string& get_status_msg() const {
return m_status_msg;
return m_status_msg;
}
private:
/// Helper function for consume. Process response line
void process(std::string::iterator begin, std::string::iterator end);
/// Helper function for processing body bytes
size_t process_body(const char *buf, size_t len);
enum state {
RESPONSE_LINE = 0,
HEADERS = 1,
BODY = 2,
DONE = 3
};
std::string m_status_msg;
size_t m_read;
lib::shared_ptr<std::string> m_buf;
status_code::value m_status_code;
state m_state;
/// Helper function for consume. Process response line
void process(std::string::iterator begin, std::string::iterator end);
/// Helper function for processing body bytes
size_t process_body(const char *buf, size_t len);
enum state {
RESPONSE_LINE = 0,
HEADERS = 1,
BODY = 2,
DONE = 3
};
std::string m_status_msg;
size_t m_read;
lib::shared_ptr<std::string> m_buf;
status_code::value m_status_code;
state m_state;
};

View File

@@ -75,28 +75,28 @@ template <typename config>
lib::error_code connection<config>::send(const std::string& payload,
frame::opcode::value op)
{
message_ptr msg = m_msg_manager->get_message(op,payload.size());
msg->append_payload(payload);
return send(msg);
message_ptr msg = m_msg_manager->get_message(op,payload.size());
msg->append_payload(payload);
return send(msg);
}
template <typename config>
lib::error_code connection<config>::send(const void* payload, size_t len,
frame::opcode::value op)
{
message_ptr msg = m_msg_manager->get_message(op,len);
msg->append_payload(payload,len);
return send(msg);
message_ptr msg = m_msg_manager->get_message(op,len);
msg->append_payload(payload,len);
return send(msg);
}
template <typename config>
lib::error_code connection<config>::send(typename config::message_type::ptr msg)
{
m_alog.write(log::alevel::devel,"connection send");
// TODO:
// TODO:
if (m_state != session::state::open) {
return error::make_error_code(error::invalid_state);
}
@@ -111,29 +111,29 @@ lib::error_code connection<config>::send(typename config::message_type::ptr msg)
write_push(outgoing_msg);
needs_writing = !m_write_flag && !m_send_queue.empty();
} else {
outgoing_msg = m_msg_manager->get_message();
if (!outgoing_msg) {
return error::make_error_code(error::no_outgoing_buffers);
}
scoped_lock_type lock(m_write_lock);
lib::error_code ec = m_processor->prepare_data_frame(msg,outgoing_msg);
if (ec) {
return ec;
}
outgoing_msg = m_msg_manager->get_message();
if (!outgoing_msg) {
return error::make_error_code(error::no_outgoing_buffers);
}
scoped_lock_type lock(m_write_lock);
lib::error_code ec = m_processor->prepare_data_frame(msg,outgoing_msg);
if (ec) {
return ec;
}
write_push(outgoing_msg);
needs_writing = !m_write_flag && !m_send_queue.empty();
}
if (needs_writing) {
transport_con_type::dispatch(lib::bind(
&type::write_frame,
type::shared_from_this()
));
}
if (needs_writing) {
transport_con_type::dispatch(lib::bind(
&type::write_frame,
type::shared_from_this()
));
}
return lib::error_code();
}
@@ -164,10 +164,10 @@ void connection<config>::ping(const std::string& payload) {
}
if (needs_writing) {
transport_con_type::dispatch(lib::bind(
&type::write_frame,
type::shared_from_this()
));
transport_con_type::dispatch(lib::bind(
&type::write_frame,
type::shared_from_this()
));
}
}
@@ -199,10 +199,10 @@ void connection<config>::pong(const std::string& payload, lib::error_code& ec) {
}
if (needs_writing) {
transport_con_type::dispatch(lib::bind(
&type::write_frame,
type::shared_from_this()
));
transport_con_type::dispatch(lib::bind(
&type::write_frame,
type::shared_from_this()
));
}
ec = lib::error_code();
@@ -549,7 +549,7 @@ void connection<config>::handle_transport_init(const lib::error_code& ec) {
if (ec) {
std::stringstream s;
s << "handle_transport_init recieved error: "<< ec.message();
s << "handle_transport_init recieved error: "<< ec.message();
m_elog.write(log::elevel::fatal,s.str());
this->terminate();
@@ -595,7 +595,7 @@ void connection<config>::read(size_t num_bytes) {
// a new read request with this function as the handler.
template <typename config>
void connection<config>::handle_handshake_read(const lib::error_code& ec,
size_t bytes_transferred)
size_t bytes_transferred)
{
m_alog.write(log::alevel::devel,"connection handle_handshake_read");
@@ -606,7 +606,7 @@ void connection<config>::handle_handshake_read(const lib::error_code& ec,
if (ec) {
std::stringstream s;
s << "error in handle_read_handshake: "<< ec.message();
s << "error in handle_read_handshake: "<< ec.message();
m_elog.write(log::elevel::fatal,s.str());
this->terminate();
return;
@@ -727,7 +727,7 @@ void connection<config>::send_http_response_error() {
// a new read request with this function as the handler.
template <typename config>
void connection<config>::handle_read_frame(const lib::error_code& ec,
size_t bytes_transferred)
size_t bytes_transferred)
{
//m_alog.write(log::alevel::devel,"connection handle_read_frame");
@@ -746,7 +746,7 @@ void connection<config>::handle_read_frame(const lib::error_code& ec,
}
std::stringstream s;
s << "error in handle_read_frame: " << ec.message() << " (" << ec << ")";
s << "error in handle_read_frame: " << ec.message() << " (" << ec << ")";
m_elog.write(log::elevel::fatal,s.str());
this->terminate();
return;
@@ -762,32 +762,32 @@ void connection<config>::handle_read_frame(const lib::error_code& ec,
size_t p = 0;
if (m_alog.static_test(log::alevel::devel)) {
std::stringstream s;
s << "p = " << p << " bytes transferred = " << bytes_transferred;
m_alog.write(log::alevel::devel,s.str());
std::stringstream s;
s << "p = " << p << " bytes transferred = " << bytes_transferred;
m_alog.write(log::alevel::devel,s.str());
}
while (p < bytes_transferred) {
if (m_alog.static_test(log::alevel::devel)) {
std::stringstream s;
s << "calling consume with " << bytes_transferred-p << " bytes";
m_alog.write(log::alevel::devel,s.str());
std::stringstream s;
s << "calling consume with " << bytes_transferred-p << " bytes";
m_alog.write(log::alevel::devel,s.str());
}
lib::error_code ec;
p += m_processor->consume(
reinterpret_cast<uint8_t*>(m_buf)+p,
bytes_transferred-p,
p += m_processor->consume(
reinterpret_cast<uint8_t*>(m_buf)+p,
bytes_transferred-p,
ec
);
if (m_alog.static_test(log::alevel::devel)) {
std::stringstream s;
s << "bytes left after consume: " << bytes_transferred-p;
m_alog.write(log::alevel::devel,s.str());
}
if (ec) {
);
if (m_alog.static_test(log::alevel::devel)) {
std::stringstream s;
s << "bytes left after consume: " << bytes_transferred-p;
m_alog.write(log::alevel::devel,s.str());
}
if (ec) {
m_elog.write(log::elevel::rerror,"consume error: "+ec.message());
if (config::drop_on_protocol_error) {
@@ -806,11 +806,11 @@ void connection<config>::handle_read_frame(const lib::error_code& ec,
}
}
return;
}
}
if (m_processor->ready()) {
if (m_processor->ready()) {
//m_alog.write(log::alevel::devel,"consume ended in ready");
message_ptr msg = m_processor->get_message();
if (!msg) {
@@ -824,7 +824,7 @@ void connection<config>::handle_read_frame(const lib::error_code& ec,
} else {
process_control_frame(msg);
}
}
}
}
transport_con_type::async_read_at_least(
@@ -934,8 +934,8 @@ bool connection<config>::process_handshake_request() {
// we don't send an empty extensions header because it breaks many
// clients.
if (neg_results.second.size() > 0) {
m_response.replace_header("Sec-WebSocket-Extensions",
neg_results.second);
m_response.replace_header("Sec-WebSocket-Extensions",
neg_results.second);
}
}
@@ -993,7 +993,7 @@ bool connection<config>::process_handshake_request() {
// TODO: does this function still need to be here?
template <typename config>
void connection<config>::handle_read(const lib::error_code& ec,
size_t bytes_transferred)
size_t bytes_transferred)
{
if (ec) {
m_elog.write(log::elevel::rerror,"error in handle_read"+ec.message());
@@ -1382,8 +1382,8 @@ void connection<config>::write_frame() {
m_send_buffer.push_back(transport::buffer(header.c_str(),header.size()));
m_send_buffer.push_back(transport::buffer(payload.c_str(),payload.size()));
if (m_alog.static_test(log::alevel::frame_header)) {
if (m_alog.dynamic_test(log::alevel::frame_header)) {
std::stringstream s;
@@ -1415,10 +1415,10 @@ template <typename config>
void connection<config>::handle_write_frame(bool terminate,
const lib::error_code& ec)
{
m_send_buffer.clear();
m_current_msg.reset();
if (ec) {
m_send_buffer.clear();
m_current_msg.reset();
if (ec) {
m_elog.write(log::elevel::fatal,"error in handle_write_frame: "+ec.message());
this->terminate();
return;
@@ -1442,10 +1442,10 @@ void connection<config>::handle_write_frame(bool terminate,
}
if (needs_writing) {
transport_con_type::dispatch(lib::bind(
&type::write_frame,
type::shared_from_this()
));
transport_con_type::dispatch(lib::bind(
&type::write_frame,
type::shared_from_this()
));
}
}
@@ -1672,10 +1672,10 @@ lib::error_code connection<config>::send_close_frame(close::status::value code,
}
if (needs_writing) {
transport_con_type::dispatch(lib::bind(
&type::write_frame,
type::shared_from_this()
));
transport_con_type::dispatch(lib::bind(
&type::write_frame,
type::shared_from_this()
));
}
return lib::error_code();

View File

@@ -35,11 +35,11 @@ typename endpoint<connection,config>::connection_ptr
endpoint<connection,config>::create_connection() {
m_alog.write(log::alevel::devel,"create_connection");
//scoped_lock_type lock(m_state_lock);
/*if (m_state == STOPPING || m_state == STOPPED) {
return connection_ptr();
}*/
/*if (m_state == STOPPING || m_state == STOPPED) {
return connection_ptr();
}*/
// Create a connection on the heap and manage it using a shared pointer
connection_ptr con(new connection_type(m_is_server,m_user_agent,m_alog,
m_elog, m_rng));
@@ -54,7 +54,7 @@ endpoint<connection,config>::create_connection() {
//
con->set_handle(w);
// Copy default handlers from the endpoint
con->set_open_handler(m_open_handler);
con->set_close_handler(m_close_handler);
@@ -66,27 +66,27 @@ endpoint<connection,config>::create_connection() {
con->set_http_handler(m_http_handler);
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);
lib::bind(
&type::remove_connection,
this,
lib::placeholders::_1
)
);
lib::error_code ec;
ec = transport_type::init(con);
if (ec) {
m_elog.write(log::elevel::fatal,ec.message());
return connection_ptr();
}
scoped_lock_type lock(m_mutex);
m_connections.insert(con);
return con;
m_connections.insert(con);
return con;
}
template <typename connection, typename config>
@@ -182,16 +182,16 @@ void endpoint<connection,config>::close(connection_hdl hdl,
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());
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);
// unregister the termination handler
con->set_termination_handler(termination_handler());
m_connections.erase(con);
}
} // namespace websocketpp

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Peter Thorson. All rights reserved.
* Copyright (c) 2013, 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:

View File

@@ -68,8 +68,8 @@ public:
void set_channels(level channels) {
if (channels == names::none) {
clear_channels(names::all);
return;
clear_channels(names::all);
return;
}
scoped_lock_type lock(m_lock);
@@ -104,20 +104,20 @@ public:
}
bool dynamic_test(level channel) {
return ((channel & m_dynamic_channels) != 0);
}
return ((channel & m_dynamic_channels) != 0);
}
private:
typedef typename concurrency::scoped_lock_type scoped_lock_type;
typedef typename concurrency::mutex_type mutex_type;
typedef typename concurrency::mutex_type mutex_type;
const char* get_timestamp() {
std::time_t t = std::time(NULL);
std::strftime(buffer,39,"%Y-%m-%d %H:%M:%S%z",std::localtime(&t));
return buffer;
}
mutex_type m_lock;
mutex_type m_lock;
char buffer[40];
const level m_static_channels;
level m_dynamic_channels;

View File

@@ -46,23 +46,23 @@ struct elevel {
static const level all = 0xffffffff;
static const char* channel_name(level channel) {
switch(channel) {
case devel:
return "devel";
case library:
return "library";
case info:
return "info";
case warn:
return "warning";
case rerror:
return "error";
case fatal:
return "fatal";
default:
return "unknown";
}
}
switch(channel) {
case devel:
return "devel";
case library:
return "library";
case info:
return "info";
case warn:
return "warning";
case rerror:
return "error";
case fatal:
return "fatal";
default:
return "unknown";
}
}
};
struct alevel {
@@ -82,35 +82,35 @@ struct alevel {
static const level all = 0xffffffff;
static const char* channel_name(level channel) {
switch(channel) {
case connect:
return "connect";
case disconnect:
return "disconnect";
case control:
return "control";
case frame_header:
return "frame_header";
case frame_payload:
return "frame_payload";
case message_header:
return "message_header";
case message_payload:
return "message_payload";
case endpoint:
return "endpoint";
case debug_handshake:
return "debug_handshake";
case debug_close:
return "debug_close";
case devel:
return "devel";
case app:
return "application";
default:
return "unknown";
}
}
switch(channel) {
case connect:
return "connect";
case disconnect:
return "disconnect";
case control:
return "control";
case frame_header:
return "frame_header";
case frame_payload:
return "frame_payload";
case message_header:
return "message_header";
case message_payload:
return "message_payload";
case endpoint:
return "endpoint";
case debug_handshake:
return "debug_handshake";
case debug_close:
return "debug_close";
case devel:
return "devel";
case app:
return "application";
default:
return "unknown";
}
}
};
} // logger

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Peter Thorson. All rights reserved.
* Copyright (c) 2013, 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:
@@ -42,12 +42,12 @@ class con_msg_manager
: public lib::enable_shared_from_this<con_msg_manager<message> >
{
public:
typedef con_msg_manager<message> type;
typedef lib::shared_ptr<con_msg_manager> ptr;
typedef lib::weak_ptr<con_msg_manager> weak_ptr;
typedef con_msg_manager<message> type;
typedef lib::shared_ptr<con_msg_manager> ptr;
typedef lib::weak_ptr<con_msg_manager> weak_ptr;
typedef typename message::ptr message_ptr;
typedef typename message::ptr message_ptr;
/// Get an empty message buffer
/**
* @return A shared pointer to an empty new message
@@ -56,30 +56,30 @@ public:
return message_ptr(new message(type::shared_from_this()));
}
/// Get a message buffer with specified size and opcode
/**
/// Get a message buffer with specified size and opcode
/**
* @param op The opcode to use
* @param size Minimum size in bytes to request for the message payload.
*
* @return A shared pointer to a new message with specified size.
*/
message_ptr get_message(frame::opcode::value op,size_t size) {
return message_ptr(new message(type::shared_from_this(),op,size));
}
* @param size Minimum size in bytes to request for the message payload.
*
* @return A shared pointer to a new message with specified size.
*/
message_ptr get_message(frame::opcode::value op,size_t size) {
return message_ptr(new message(type::shared_from_this(),op,size));
}
/// Recycle a message
/**
* This method shouldn't be called. If it is, return false to indicate an
* error. The rest of the method recycle chain should notice this and free
* the memory.
*
* @param msg The message to be recycled.
*
* @return true if the message was successfully recycled, false otherwse.
*/
bool recycle(message * msg) {
return false;
}
/// Recycle a message
/**
* This method shouldn't be called. If it is, return false to indicate an
* error. The rest of the method recycle chain should notice this and free
* the memory.
*
* @param msg The message to be recycled.
*
* @return true if the message was successfully recycled, false otherwse.
*/
bool recycle(message * msg) {
return false;
}
};
/// An endpoint message manager that allocates a new manager for each
@@ -87,15 +87,15 @@ public:
template <typename con_msg_manager>
class endpoint_msg_manager {
public:
typedef typename con_msg_manager::ptr con_msg_man_ptr;
/// Get a pointer to a connection message manager
/**
* @return A pointer to the requested connection message manager.
*/
con_msg_man_ptr get_manager() const {
return con_msg_man_ptr(new con_msg_manager());
}
typedef typename con_msg_manager::ptr con_msg_man_ptr;
/// Get a pointer to a connection message manager
/**
* @return A pointer to the requested connection message manager.
*/
con_msg_man_ptr get_manager() const {
return con_msg_man_ptr(new con_msg_manager());
}
};
} // namespace alloc

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Peter Thorson. All rights reserved.
* Copyright (c) 2013, 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:
@@ -83,11 +83,11 @@ namespace message_buffer {
template <template<class> class con_msg_manager>
class message {
public:
typedef lib::shared_ptr<message> ptr;
typedef con_msg_manager<message> con_msg_man_type;
typedef typename con_msg_man_type::ptr con_msg_man_ptr;
typedef typename con_msg_man_type::weak_ptr con_msg_man_weak_ptr;
typedef lib::shared_ptr<message> ptr;
typedef con_msg_manager<message> con_msg_man_type;
typedef typename con_msg_man_type::ptr con_msg_man_ptr;
typedef typename con_msg_man_type::weak_ptr con_msg_man_weak_ptr;
/// Construct an empty message
/**
@@ -104,17 +104,17 @@ public:
/**
*
*/
message(const con_msg_man_ptr manager, frame::opcode::value op, size_t size = 128)
: m_manager(manager)
, m_opcode(op)
, m_prepared(false)
message(const con_msg_man_ptr manager, frame::opcode::value op, size_t size = 128)
: m_manager(manager)
, m_opcode(op)
, m_prepared(false)
, m_fin(true)
, m_terminal(false)
, m_compressed(false)
{
m_payload.reserve(size);
}
{
m_payload.reserve(size);
}
/// Return whether or not the message has been prepared for sending
/**
* The prepared flag indicates that the message has been prepared by a
@@ -122,17 +122,17 @@ public:
*
* @return whether or not the message has been prepared for sending
*/
bool get_prepared() const {
return m_prepared;
}
bool get_prepared() const {
return m_prepared;
}
/// Set or clear the flag that indicates that the message has been prepared
/**
* @param value The value to set the prepared flag to
*/
void set_prepared(bool value) {
m_prepared = value;
}
void set_prepared(bool value) {
m_prepared = value;
}
/// Return whether or not the message is flagged as compressed
/**
@@ -141,17 +141,17 @@ public:
*
* @return whether or not the message is/should be compressed
*/
bool get_compressed() const {
return m_compressed;
}
bool get_compressed() const {
return m_compressed;
}
/// Set or clear the compression flag
/**
* @param value The value to set the compressed flag to
*/
void set_compressed(bool value) {
m_compressed = value;
}
void set_compressed(bool value) {
m_compressed = value;
}
/// Get whether or not the message is terminal
/**
@@ -197,9 +197,9 @@ public:
}
/// Return the message opcode
frame::opcode::value get_opcode() const {
return m_opcode;
}
frame::opcode::value get_opcode() const {
return m_opcode;
}
/// Set the opcode
void set_opcode(frame::opcode::value op) {
@@ -211,9 +211,9 @@ public:
* This value is typically set by a websocket protocol processor
* and shouldn't be tampered with.
*/
const std::string& get_header() const {
return m_header;
}
const std::string& get_header() const {
return m_header;
}
/// Set prepared frame header
/**
@@ -221,78 +221,78 @@ public:
*
* @param header A string to set the header to.
*/
void set_header(const std::string& header) {
m_header = header;
}
void set_header(const std::string& header) {
m_header = header;
}
const std::string& get_extension_data() const {
return m_extension_data;
}
return m_extension_data;
}
/// Get a reference to the payload string
/**
* @return A const reference to the message's payload string
*/
const std::string& get_payload() const {
return m_payload;
}
return m_payload;
}
/// Get a non-const reference to the payload string
/**
* @return A reference to the message's payload string
*/
std::string& get_raw_payload() {
return m_payload;
}
std::string& get_raw_payload() {
return m_payload;
}
void set_payload(const std::string& payload) {
m_payload = payload;
}
void set_payload(const void *payload, size_t len) {
m_payload.reserve(len);
const char* pl = static_cast<const char *>(payload);
m_payload.assign(pl, pl + len);
}
void append_payload(const std::string& payload) {
m_payload.append(payload);
}
void append_payload(const void *payload, size_t len) {
m_payload.reserve(m_payload.size()+len);
m_payload.append(static_cast<const char *>(payload),len);
}
void set_payload(const std::string& payload) {
m_payload = payload;
}
void set_payload(const void *payload, size_t len) {
m_payload.reserve(len);
const char* pl = static_cast<const char *>(payload);
m_payload.assign(pl, pl + len);
}
void append_payload(const std::string& payload) {
m_payload.append(payload);
}
void append_payload(const void *payload, size_t len) {
m_payload.reserve(m_payload.size()+len);
m_payload.append(static_cast<const char *>(payload),len);
}
/// Recycle the message
/**
* A request to recycle this message was received. Forward that request to
* the connection message manager for processing. Errors and exceptions
* from the manager's recycle member function should be passed back up the
* call chain. The caller to message::recycle will deal with them.
*
* Recycle must *only* be called by the message shared_ptr's destructor.
* Once recycled successfully, ownership of the memory has been passed to
* another system and must not be accessed again.
*
* @return true if the message was successfully recycled, false otherwise.
*/
bool recycle() {
con_msg_man_ptr shared = m_manager.lock();
/// Recycle the message
/**
* A request to recycle this message was received. Forward that request to
* the connection message manager for processing. Errors and exceptions
* from the manager's recycle member function should be passed back up the
* call chain. The caller to message::recycle will deal with them.
*
* Recycle must *only* be called by the message shared_ptr's destructor.
* Once recycled successfully, ownership of the memory has been passed to
* another system and must not be accessed again.
*
* @return true if the message was successfully recycled, false otherwise.
*/
bool recycle() {
con_msg_man_ptr shared = m_manager.lock();
if (shared) {
return shared->recycle(this);
} else {
return false;
}
}
if (shared) {
return shared->recycle(this);
} else {
return false;
}
}
private:
con_msg_man_weak_ptr m_manager;
std::string m_header;
std::string m_extension_data;
std::string m_payload;
frame::opcode::value m_opcode;
bool m_prepared;
con_msg_man_weak_ptr m_manager;
std::string m_header;
std::string m_extension_data;
std::string m_payload;
frame::opcode::value m_opcode;
bool m_prepared;
bool m_fin;
bool m_terminal;
bool m_compressed;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, Peter Thorson. All rights reserved.
* Copyright (c) 2013, 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:
@@ -82,14 +82,14 @@ namespace message_buffer {
*/
template <typename T>
void message_deleter(T* msg) {
try {
if (!msg->recycle()) {
delete msg;
}
} catch (...) {
// TODO: is there a better way to ensure this function doesn't throw?
delete msg;
}
try {
if (!msg->recycle()) {
delete msg;
}
} catch (...) {
// TODO: is there a better way to ensure this function doesn't throw?
delete msg;
}
}
/// Represents a buffer for a single WebSocket message.
@@ -100,56 +100,56 @@ void message_deleter(T* msg) {
template <typename con_msg_manager>
class message {
public:
typedef lib::shared_ptr<message> ptr;
typedef typename con_msg_manager::weak_ptr con_msg_man_ptr;
typedef lib::shared_ptr<message> ptr;
typedef typename con_msg_manager::weak_ptr con_msg_man_ptr;
message(con_msg_man_ptr manager, size_t size = 128)
: m_manager(manager)
, m_payload(size) {}
message(con_msg_man_ptr manager, size_t size = 128)
: m_manager(manager)
, m_payload(size) {}
frame::opcode::value get_opcode() const {
return m_opcode;
}
const std::string& get_header() const {
return m_header;
}
const std::string& get_extension_data() const {
return m_extension_data;
}
const std::string& get_payload() const {
return m_payload;
}
/// Recycle the message
/**
* A request to recycle this message was received. Forward that request to
* the connection message manager for processing. Errors and exceptions
* from the manager's recycle member function should be passed back up the
* call chain. The caller to message::recycle will deal with them.
*
* Recycle must *only* be called by the message shared_ptr's destructor.
* Once recycled successfully, ownership of the memory has been passed to
* another system and must not be accessed again.
*
* @return true if the message was successfully recycled, false otherwise.
*/
bool recycle() {
typename con_msg_manager::ptr shared = m_manager.lock();
frame::opcode::value get_opcode() const {
return m_opcode;
}
const std::string& get_header() const {
return m_header;
}
const std::string& get_extension_data() const {
return m_extension_data;
}
const std::string& get_payload() const {
return m_payload;
}
/// Recycle the message
/**
* A request to recycle this message was received. Forward that request to
* the connection message manager for processing. Errors and exceptions
* from the manager's recycle member function should be passed back up the
* call chain. The caller to message::recycle will deal with them.
*
* Recycle must *only* be called by the message shared_ptr's destructor.
* Once recycled successfully, ownership of the memory has been passed to
* another system and must not be accessed again.
*
* @return true if the message was successfully recycled, false otherwise.
*/
bool recycle() {
typename con_msg_manager::ptr shared = m_manager.lock();
if (shared) {
return shared->(recycle(this));
} else {
return false;
}
}
if (shared) {
return shared->(recycle(this));
} else {
return false;
}
}
private:
con_msg_man_ptr m_manager;
frame::opcode::value m_opcode;
std::string m_header;
std::string m_extension_data;
std::string m_payload;
con_msg_man_ptr m_manager;
frame::opcode::value m_opcode;
std::string m_header;
std::string m_extension_data;
std::string m_payload;
};
namespace alloc {
@@ -159,34 +159,34 @@ namespace alloc {
template <typename message>
class con_msg_manager {
public:
typedef lib::shared_ptr<con_msg_manager> ptr;
typedef lib::weak_ptr<con_msg_manager> weak_ptr;
typedef lib::shared_ptr<con_msg_manager> ptr;
typedef lib::weak_ptr<con_msg_manager> weak_ptr;
typedef typename message::ptr message_ptr;
/// Get a message buffer with specified size
/**
* @param size Minimum size in bytes to request for the message payload.
*
* @return A shared pointer to a new message with specified size.
*/
message_ptr get_message(size_t size) const {
return message_ptr(new message(size));
}
/// Recycle a message
/**
* This method shouldn't be called. If it is, return false to indicate an
* error. The rest of the method recycle chain should notice this and free
* the memory.
*
* @param msg The message to be recycled.
*
* @return true if the message was successfully recycled, false otherwse.
*/
bool recycle(message * msg) {
return false;
}
typedef typename message::ptr message_ptr;
/// Get a message buffer with specified size
/**
* @param size Minimum size in bytes to request for the message payload.
*
* @return A shared pointer to a new message with specified size.
*/
message_ptr get_message(size_t size) const {
return message_ptr(new message(size));
}
/// Recycle a message
/**
* This method shouldn't be called. If it is, return false to indicate an
* error. The rest of the method recycle chain should notice this and free
* the memory.
*
* @param msg The message to be recycled.
*
* @return true if the message was successfully recycled, false otherwse.
*/
bool recycle(message * msg) {
return false;
}
};
/// An endpoint message manager that allocates a new manager for each
@@ -194,15 +194,15 @@ public:
template <typename con_msg_manager>
class endpoint_msg_manager {
public:
typedef typename con_msg_manager::ptr con_msg_man_ptr;
/// Get a pointer to a connection message manager
/**
* @return A pointer to the requested connection message manager.
*/
con_msg_man_ptr get_manager() const {
return con_msg_man_ptr(new con_msg_manager());
}
typedef typename con_msg_manager::ptr con_msg_man_ptr;
/// Get a pointer to a connection message manager
/**
* @return A pointer to the requested connection message manager.
*/
con_msg_man_ptr get_manager() const {
return con_msg_man_ptr(new con_msg_manager());
}
};
} // namespace alloc
@@ -214,7 +214,7 @@ namespace pool {
class con_msg_manager {
};
/// An endpoint manager that maintains a shared pool of connection managers
/// and returns an appropriate one for the requesting connection.
class endpoint_msg_manager {

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Peter Thorson. All rights reserved.
* Copyright (c) 2013, 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:
@@ -54,11 +54,11 @@ static const char handshake_guid[] = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
// Processor class related error codes
namespace error_cat {
enum value {
BAD_REQUEST = 0, // Error was the result of improperly formatted user input
INTERNAL_ERROR = 1, // Error was a logic error internal to WebSocket++
PROTOCOL_VIOLATION = 2,
MESSAGE_TOO_BIG = 3,
PAYLOAD_VIOLATION = 4 // Error was due to receiving invalid payload data
BAD_REQUEST = 0, // Error was the result of improperly formatted user input
INTERNAL_ERROR = 1, // Error was a logic error internal to WebSocket++
PROTOCOL_VIOLATION = 2,
MESSAGE_TOO_BIG = 3,
PAYLOAD_VIOLATION = 4 // Error was due to receiving invalid payload data
};
} // namespace error_cat
@@ -166,44 +166,44 @@ enum processor_errors {
class processor_category : public lib::error_category {
public:
processor_category() {}
processor_category() {}
const char *name() const _WEBSOCKETPP_NOEXCEPT_TOKEN_ {
return "websocketpp.processor";
}
std::string message(int value) const {
switch(value) {
case error::general:
return "Generic processor error";
case error::bad_request:
return "invalid user input";
case error::protocol_violation:
return "Generic protocol violation";
case error::message_too_big:
return "A message was too large";
case error::invalid_payload:
return "A payload contained invalid data";
case error::invalid_arguments:
return "invalid function arguments";
case error::invalid_opcode:
return "invalid opcode";
case error::control_too_big:
return "Control messages are limited to fewer than 125 characters";
case error::invalid_rsv_bit:
return "Invalid use of reserved bits";
case error::fragmented_control:
return "Control messages cannot be fragmented";
case error::invalid_continuation:
return "Invalid message continuation";
case error::masking_required:
return "Clients may not send unmasked frames";
case error::masking_forbidden:
return "Servers may not send masked frames";
case error::non_minimal_encoding:
return "Payload length was not minimally encoded";
case error::requires_64bit:
return "64 bit frames are not supported on 32 bit systems";
const char *name() const _WEBSOCKETPP_NOEXCEPT_TOKEN_ {
return "websocketpp.processor";
}
std::string message(int value) const {
switch(value) {
case error::general:
return "Generic processor error";
case error::bad_request:
return "invalid user input";
case error::protocol_violation:
return "Generic protocol violation";
case error::message_too_big:
return "A message was too large";
case error::invalid_payload:
return "A payload contained invalid data";
case error::invalid_arguments:
return "invalid function arguments";
case error::invalid_opcode:
return "invalid opcode";
case error::control_too_big:
return "Control messages are limited to fewer than 125 characters";
case error::invalid_rsv_bit:
return "Invalid use of reserved bits";
case error::fragmented_control:
return "Control messages cannot be fragmented";
case error::invalid_continuation:
return "Invalid message continuation";
case error::masking_required:
return "Clients may not send unmasked frames";
case error::masking_forbidden:
return "Servers may not send masked frames";
case error::non_minimal_encoding:
return "Payload length was not minimally encoded";
case error::requires_64bit:
return "64 bit frames are not supported on 32 bit systems";
case error::invalid_utf8:
return "Invalid UTF8 encoding";
case error::not_implimented:
@@ -232,19 +232,19 @@ public:
return "Error parsing extension header";
case error::extensions_disabled:
return "Extensions are disabled";
default:
return "Unknown";
}
}
default:
return "Unknown";
}
}
};
inline const lib::error_category& get_processor_category() {
static processor_category instance;
return instance;
static processor_category instance;
return instance;
}
inline lib::error_code make_error_code(error::processor_errors e) {
return lib::error_code(static_cast<int>(e), get_processor_category());
return lib::error_code(static_cast<int>(e), get_processor_category());
}
/// Converts a processor error_code into a websocket close code

View File

@@ -32,9 +32,9 @@
// For htonl
#if defined(WIN32)
#include <winsock2.h>
#include <winsock2.h>
#else
#include <arpa/inet.h>
#include <arpa/inet.h>
#endif
#include <websocketpp/processors/processor.hpp>
@@ -56,13 +56,13 @@ class hybi00 : public processor<config> {
public:
typedef processor<config> base;
typedef typename config::request_type request_type;
typedef typename config::response_type response_type;
typedef typename config::message_type message_type;
typedef typename message_type::ptr message_ptr;
typedef typename config::request_type request_type;
typedef typename config::response_type response_type;
typedef typename config::message_type message_type;
typedef typename message_type::ptr message_ptr;
typedef typename config::con_msg_manager_type::ptr msg_manager_ptr;
typedef typename config::con_msg_manager_type::ptr msg_manager_ptr;
explicit hybi00(bool secure, bool server, msg_manager_ptr manager)
: processor<config>(secure, server)
@@ -206,14 +206,14 @@ public:
return "";
}
/// Process new websocket connection bytes
size_t consume(uint8_t * buf, size_t len, lib::error_code & ec) {
/// Process new websocket connection bytes
size_t consume(uint8_t * buf, size_t len, lib::error_code & ec) {
// if in state header we are expecting a 0x00 byte, if we don't get one
// it is a fatal error
size_t p = 0; // bytes processed
size_t l = 0;
ec = lib::error_code();
ec = lib::error_code();
while (p < len) {
if (m_state == HEADER) {
@@ -262,63 +262,63 @@ public:
//ec = make_error_code(error::not_implimented);
return p;
}
}
bool ready() const {
return (m_state == READY);
}
bool get_error() const {
return false;
}
bool ready() const {
return (m_state == READY);
}
bool get_error() const {
return false;
}
message_ptr get_message() {
message_ptr ret = m_msg_ptr;
message_ptr get_message() {
message_ptr ret = m_msg_ptr;
m_msg_ptr = message_ptr();
m_state = HEADER;
return ret;
}
/// Prepare a message for writing
/**
* Performs validation, masking, compression, etc. will return an error if
* there was an error, otherwise msg will be ready to be written
*/
virtual lib::error_code prepare_data_frame(message_ptr in, message_ptr out)
{
if (!in || !out) {
return make_error_code(error::invalid_arguments);
}
// TODO: check if the message is prepared already
// validate opcode
}
/// Prepare a message for writing
/**
* Performs validation, masking, compression, etc. will return an error if
* there was an error, otherwise msg will be ready to be written
*/
virtual lib::error_code prepare_data_frame(message_ptr in, message_ptr out)
{
if (!in || !out) {
return make_error_code(error::invalid_arguments);
}
// TODO: check if the message is prepared already
// validate opcode
if (in->get_opcode() != frame::opcode::text) {
return make_error_code(error::invalid_opcode);
}
std::string& i = in->get_raw_payload();
//std::string& o = out->get_raw_payload();
//std::string& o = out->get_raw_payload();
// validate payload utf8
if (!utf8_validator::validate(i)) {
// validate payload utf8
if (!utf8_validator::validate(i)) {
return make_error_code(error::invalid_payload);
}
// generate header
// generate header
out->set_header(std::string(reinterpret_cast<const char*>(&msg_hdr),1));
// process payload
out->set_payload(i);
out->append_payload(std::string(reinterpret_cast<const char*>(&msg_ftr),1));
// hybi00 doesn't support compression
// hybi00 doesn't have masking
// hybi00 doesn't support compression
// hybi00 doesn't have masking
out->set_prepared(true);
return lib::error_code();
}
return lib::error_code();
}
lib::error_code prepare_ping(const std::string & in, message_ptr out) const
{
@@ -372,11 +372,11 @@ private:
}
enum state {
HEADER = 0,
PAYLOAD = 1,
READY = 2,
FATAL_ERROR = 3
};
HEADER = 0,
PAYLOAD = 1,
READY = 2,
FATAL_ERROR = 3
};
const uint8_t msg_hdr;
const uint8_t msg_ftr;
@@ -384,7 +384,7 @@ private:
state m_state;
msg_manager_ptr m_msg_manager;
message_ptr m_msg_ptr;
message_ptr m_msg_ptr;
utf8_validator::validator m_validator;
};

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Peter Thorson. All rights reserved.
* Copyright (c) 2013, 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:
@@ -43,10 +43,10 @@ public:
typedef typename config::request_type request_type;
typedef typename config::con_msg_manager_type::ptr msg_manager_ptr;
typedef typename config::rng_type rng_type;
explicit hybi07(bool secure,bool server, msg_manager_ptr manager,
rng_type& rng)
typedef typename config::rng_type rng_type;
explicit hybi07(bool secure,bool server, msg_manager_ptr manager,
rng_type& rng)
: hybi08<config>(secure, server, manager, rng) {}
// outgoing client connection processing is not supported for this version

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Peter Thorson. All rights reserved.
* Copyright (c) 2013, 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:
@@ -40,10 +40,10 @@ namespace processor {
template <typename config>
class hybi08 : public hybi13<config> {
public:
typedef hybi08<config> type;
typedef typename config::request_type request_type;
typedef typename config::con_msg_manager_type::ptr msg_manager_ptr;
typedef hybi08<config> type;
typedef typename config::request_type request_type;
typedef typename config::con_msg_manager_type::ptr msg_manager_ptr;
typedef typename config::rng_type rng_type;
explicit hybi08(bool secure, bool server, msg_manager_ptr manager,

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Peter Thorson. All rights reserved.
* Copyright (c) 2013, 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:
@@ -53,25 +53,25 @@ namespace processor {
*/
template <typename request_type>
bool is_websocket_handshake(request_type& r) {
using utility::ci_find_substr;
const std::string& upgrade_header = r.get_header("Upgrade");
if (ci_find_substr(upgrade_header, constants::upgrade_token,
sizeof(constants::upgrade_token)-1) == upgrade_header.end())
{
return false;
}
const std::string& con_header = r.get_header("Connection");
if (ci_find_substr(con_header, constants::connection_token,
sizeof(constants::connection_token)-1) == con_header.end())
{
return false;
}
using utility::ci_find_substr;
const std::string& upgrade_header = r.get_header("Upgrade");
if (ci_find_substr(upgrade_header, constants::upgrade_token,
sizeof(constants::upgrade_token)-1) == upgrade_header.end())
{
return false;
}
const std::string& con_header = r.get_header("Connection");
if (ci_find_substr(con_header, constants::connection_token,
sizeof(constants::connection_token)-1) == con_header.end())
{
return false;
}
return true;
return true;
}
/// Extract the version from a WebSocket handshake request
@@ -98,7 +98,7 @@ int get_websocket_version(request_type& r) {
int version;
std::istringstream ss(r.get_header("Sec-WebSocket-Version"));
if ((ss >> version).fail()) {
return -1;
}
@@ -121,7 +121,7 @@ int get_websocket_version(request_type& r) {
//
// while(len = read(buf)) {
// if (processor.consume(buf,len) == 0) {
// // handle errors
// // handle errors
// }
// if (processor.ready()) {
// message_ptr msg = processor.get_message();
@@ -135,18 +135,18 @@ class processor {
public:
typedef processor<config> type;
typedef typename config::request_type request_type;
typedef typename config::response_type response_type;
typedef typename config::message_type::ptr message_ptr;
typedef typename config::response_type response_type;
typedef typename config::message_type::ptr message_ptr;
typedef std::pair<lib::error_code,std::string> err_str_pair;
explicit processor(bool secure, bool server)
: m_secure(secure)
, m_server(server) {}
, m_server(server) {}
virtual ~processor() {}
/// Returns the version of the WebSocket protocol that this processor
/// understands.
/// understands.
virtual int get_version() const = 0;
/// Returns whether or not the permessage_compress extension is implimented
@@ -171,8 +171,8 @@ public:
/// validate a WebSocket handshake request for this version
/**
* @param r The WebSocket handshake request to validate.
* is_websocket_handshake(r) must be true and get_websocket_version(r)
* must equal this->get_version().
* is_websocket_handshake(r) must be true and get_websocket_version(r)
* must equal this->get_version().
*
* @return A status code, 0 on success, non-zero for specific sorts of
* failure
@@ -218,7 +218,7 @@ public:
/// Return the value of the header containing the CORS origin.
virtual const std::string& get_origin(const request_type& request)
const = 0;
const = 0;
/// Extracts requested subprotocols from a handshake request
/**
@@ -236,62 +236,62 @@ public:
/// Extracts client uri from a handshake request
virtual uri_ptr get_uri(const request_type& request) const = 0;
/// process new websocket connection bytes
/**
* WebSocket connections are a continous stream of bytes that must be
* interpreted by a protocol processor into discrete frames.
*
* @param buf Buffer from which bytes should be read.
*
* @param len Length of buffer
/// process new websocket connection bytes
/**
* WebSocket connections are a continous stream of bytes that must be
* interpreted by a protocol processor into discrete frames.
*
* @param buf Buffer from which bytes should be read.
*
* @param len Length of buffer
*
* @param ec Reference to an error code to return any errors in
*
* @return Number of bytes processed
*/
virtual size_t consume(uint8_t *buf, size_t len, lib::error_code & ec) = 0;
/// Checks if there is a message ready
/**
* Checks if the most recent consume operation processed enough bytes to
* complete a new WebSocket message. The message can be retrieved by calling
* get_message() which will reset the internal state to not-ready and allow
* consume to read more bytes.
*
* @return Whether or not a message is ready.
*/
virtual bool ready() const = 0;
*
* @return Number of bytes processed
*/
virtual size_t consume(uint8_t *buf, size_t len, lib::error_code & ec) = 0;
/// Checks if there is a message ready
/**
* Checks if the most recent consume operation processed enough bytes to
* complete a new WebSocket message. The message can be retrieved by calling
* get_message() which will reset the internal state to not-ready and allow
* consume to read more bytes.
*
* @return Whether or not a message is ready.
*/
virtual bool ready() const = 0;
/// Retrieves the most recently processed message
/**
* Retrieves a shared pointer to the recently completed message if there is
* one. If ready() returns true then there is a message avaliable.
* Retrieving the message with get_message will reset the state of ready.
* As such, each new message may be retrieved only once. Calling get_message
* when there is no message avaliable will result in a null pointer being
* returned.
*
* @return A pointer to the most recently processed message or a null shared
* pointer.
*/
virtual message_ptr get_message() = 0;
/// Tests whether the processor is in a fatal error state
virtual bool get_error() const = 0;
/// Retrieves the most recently processed message
/**
* Retrieves a shared pointer to the recently completed message if there is
* one. If ready() returns true then there is a message avaliable.
* Retrieving the message with get_message will reset the state of ready.
* As such, each new message may be retrieved only once. Calling get_message
* when there is no message avaliable will result in a null pointer being
* returned.
*
* @return A pointer to the most recently processed message or a null shared
* pointer.
*/
virtual message_ptr get_message() = 0;
/// Tests whether the processor is in a fatal error state
virtual bool get_error() const = 0;
/// Retrieves the number of bytes presently needed by the processor
/// This value may be used as a hint to the transport layer as to how many
/// Retrieves the number of bytes presently needed by the processor
/// This value may be used as a hint to the transport layer as to how many
/// bytes to wait for before running consume again.
virtual size_t get_bytes_needed() const {
return 1;
}
/// Prepare a data message for writing
/**
* Performs validation, masking, compression, etc. will return an error if
* there was an error, otherwise msg will be ready to be written
*/
virtual lib::error_code prepare_data_frame(message_ptr in, message_ptr out)
virtual size_t get_bytes_needed() const {
return 1;
}
/// Prepare a data message for writing
/**
* Performs validation, masking, compression, etc. will return an error if
* there was an error, otherwise msg will be ready to be written
*/
virtual lib::error_code prepare_data_frame(message_ptr in, message_ptr out)
= 0;
/// Prepare a ping frame
@@ -341,7 +341,7 @@ public:
const std::string & reason, message_ptr out) const = 0;
protected:
const bool m_secure;
const bool m_server;
const bool m_server;
};

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Peter Thorson. All rights reserved.
* Copyright (c) 2013, 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:
@@ -42,13 +42,13 @@ namespace none {
*/
template <typename int_type>
class int_generator {
public:
int_generator() {}
/// advances the engine's state and returns the generated value
int_type operator()() {
return 0;
}
public:
int_generator() {}
/// advances the engine's state and returns the generated value
int_type operator()() {
return 0;
}
};
} // namespace none

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Peter Thorson. All rights reserved.
* Copyright (c) 2013, 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:
@@ -50,26 +50,26 @@ namespace random_device {
*/
template <typename int_type, typename concurrency>
class int_generator {
public:
typedef typename concurrency::scoped_lock_type scoped_lock_type;
typedef typename concurrency::mutex_type mutex_type;
/// constructor
//mac TODO: figure out if signed types present a range problem
int_generator() {}
/// advances the engine's state and returns the generated value
int_type operator()() {
scoped_lock_type guard(m_lock);
return m_dis(m_rng);
}
private:
lib::random_device m_rng;
lib::uniform_int_distribution<int_type> m_dis;
mutex_type m_lock;
public:
typedef typename concurrency::scoped_lock_type scoped_lock_type;
typedef typename concurrency::mutex_type mutex_type;
/// constructor
//mac TODO: figure out if signed types present a range problem
int_generator() {}
/// advances the engine's state and returns the generated value
int_type operator()() {
scoped_lock_type guard(m_lock);
return m_dis(m_rng);
}
private:
lib::random_device m_rng;
lib::uniform_int_distribution<int_type> m_dis;
mutex_type m_lock;
};
} // namespace random_device

View File

@@ -35,7 +35,7 @@ namespace role {
class client {
public:
static bool is_server = false;
static bool is_server = false;
}
} // namespace role

View File

@@ -44,16 +44,16 @@ template <typename config>
class client : public endpoint<connection<config>,config> {
public:
/// Type of this endpoint
typedef client<config> type;
/// Type of the endpoint concurrency component
typedef typename config::concurrency_type concurrency_type;
typedef client<config> type;
/// Type of the endpoint concurrency component
typedef typename config::concurrency_type concurrency_type;
/// Type of the endpoint transport component
typedef typename config::transport_type transport_type;
/// Type of the connections this server will create
typedef connection<config> connection_type;
/// Type of a shared pointer to the connections this server will create
typedef typename config::transport_type transport_type;
/// Type of the connections this server will create
typedef connection<config> connection_type;
/// Type of a shared pointer to the connections this server will create
typedef typename connection_type::ptr connection_ptr;
/// Type of the connection transport component
@@ -61,26 +61,26 @@ public:
/// Type of a shared pointer to the connection transport component
typedef typename transport_con_type::ptr transport_con_ptr;
/// Type of the endpoint component of this server
typedef endpoint<connection_type,config> endpoint_type;
explicit client() : endpoint_type(false)
{
endpoint_type::m_alog.write(log::alevel::devel,
/// Type of the endpoint component of this server
typedef endpoint<connection_type,config> endpoint_type;
explicit client() : endpoint_type(false)
{
endpoint_type::m_alog.write(log::alevel::devel,
"client constructor");
}
/// Get a new connection
/**
* Creates and returns a pointer to a new connection to the given URI
* suitable for passing to connect(connection_ptr). This method allows
* applying connection specific settings before performing the opening
* handshake.
*
* @return A connection_ptr to the new connection
*/
connection_ptr get_connection(const std::string& u, lib::error_code &ec) {
// parse uri
}
/// Get a new connection
/**
* Creates and returns a pointer to a new connection to the given URI
* suitable for passing to connect(connection_ptr). This method allows
* applying connection specific settings before performing the opening
* handshake.
*
* @return A connection_ptr to the new connection
*/
connection_ptr get_connection(const std::string& u, lib::error_code &ec) {
// parse uri
try {
// uri validation
uri_ptr location(new uri(u));
@@ -107,36 +107,36 @@ public:
ec = error::make_error_code(error::invalid_uri);
return connection_ptr();
}
}
/// Begin the connection process for the given connection
/**
* Initiates the opening connection handshake for connection con. Exact
* behavior depends on the underlying transport policy.
*
}
/// Begin the connection process for the given connection
/**
* Initiates the opening connection handshake for connection con. Exact
* behavior depends on the underlying transport policy.
*
* @param con The connection to connect
*
* @return The pointer to the connection originally passed in.
*/
connection_ptr connect(connection_ptr con) {
// Ask transport to perform a connection
* @return The pointer to the connection originally passed in.
*/
connection_ptr connect(connection_ptr con) {
// Ask transport to perform a connection
transport_type::async_connect(
lib::static_pointer_cast<transport_con_type>(con),
con->get_uri(),
lib::bind(
&type::handle_connect,
this,
lib::placeholders::_1,
lib::placeholders::_2
)
);
lib::static_pointer_cast<transport_con_type>(con),
con->get_uri(),
lib::bind(
&type::handle_connect,
this,
lib::placeholders::_1,
lib::placeholders::_2
)
);
return con;
}
// connect(...)
return con;
}
// connect(...)
private:
// handle_connect
void handle_connect(connection_hdl hdl, const lib::error_code & ec) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Peter Thorson. All rights reserved.
* Copyright (c) 2013, 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:
@@ -35,7 +35,7 @@ namespace role {
class server {
public:
static bool is_server = true;
static bool is_server = true;
}
} // namespace role

View File

@@ -44,16 +44,16 @@ template <typename config>
class server : public endpoint<connection<config>,config> {
public:
/// Type of this endpoint
typedef server<config> type;
/// Type of the endpoint concurrency component
typedef typename config::concurrency_type concurrency_type;
typedef server<config> type;
/// Type of the endpoint concurrency component
typedef typename config::concurrency_type concurrency_type;
/// Type of the endpoint transport component
typedef typename config::transport_type transport_type;
/// Type of the connections this server will create
typedef connection<config> connection_type;
/// Type of a shared pointer to the connections this server will create
typedef typename config::transport_type transport_type;
/// Type of the connections this server will create
typedef connection<config> connection_type;
/// Type of a shared pointer to the connections this server will create
typedef typename connection_type::ptr connection_ptr;
/// Type of the connection transport component
@@ -61,42 +61,42 @@ public:
/// Type of a shared pointer to the connection transport component
typedef typename transport_con_type::ptr transport_con_ptr;
/// Type of the endpoint component of this server
typedef endpoint<connection_type,config> endpoint_type;
// TODO: clean up these types
/// Type of the endpoint component of this server
typedef endpoint<connection_type,config> endpoint_type;
// TODO: clean up these types
explicit server() : endpoint_type(true)
{
endpoint_type::m_alog.write(log::alevel::devel,
explicit server() : endpoint_type(true)
{
endpoint_type::m_alog.write(log::alevel::devel,
"server constructor");
}
// return an initialized connection_ptr. Call start() on this object to
// begin the processing loop.
connection_ptr get_connection() {
connection_ptr con = endpoint_type::create_connection();
return con;
}
// Starts the server's async connection acceptance loop.
void start_accept() {
connection_ptr con = get_connection();
transport_type::async_accept(
lib::static_pointer_cast<transport_con_type>(con),
lib::bind(
&type::handle_accept,
this,
lib::placeholders::_1,
lib::placeholders::_2
)
);
}
void handle_accept(connection_hdl hdl, const lib::error_code& ec) {
}
// return an initialized connection_ptr. Call start() on this object to
// begin the processing loop.
connection_ptr get_connection() {
connection_ptr con = endpoint_type::create_connection();
return con;
}
// Starts the server's async connection acceptance loop.
void start_accept() {
connection_ptr con = get_connection();
transport_type::async_accept(
lib::static_pointer_cast<transport_con_type>(con),
lib::bind(
&type::handle_accept,
this,
lib::placeholders::_1,
lib::placeholders::_2
)
);
}
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);
@@ -122,10 +122,10 @@ public:
con->start();
}
}
// TODO: are there cases where we should terminate this loop?
start_accept();
}
start_accept();
}
private:
};

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Peter Thorson. All rights reserved.
* Copyright (c) 2013, 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:
@@ -67,35 +67,35 @@ enum value {
class category : public lib::error_category {
public:
const char *name() const _WEBSOCKETPP_NOEXCEPT_TOKEN_ {
return "websocketpp.transport.asio";
}
std::string message(int value) const {
switch(value) {
case error::general:
return "Generic asio transport policy error";
case error::invalid_num_bytes:
return "async_read_at_least call requested more bytes than buffer can store";
case error::pass_through:
return "Underlying Transport Error";
case error::proxy_failed:
return "Proxy connection failed";
case error::proxy_invalid:
return "Invalid proxy URI";
default:
return "Unknown";
}
}
const char *name() const _WEBSOCKETPP_NOEXCEPT_TOKEN_ {
return "websocketpp.transport.asio";
}
std::string message(int value) const {
switch(value) {
case error::general:
return "Generic asio transport policy error";
case error::invalid_num_bytes:
return "async_read_at_least call requested more bytes than buffer can store";
case error::pass_through:
return "Underlying Transport Error";
case error::proxy_failed:
return "Proxy connection failed";
case error::proxy_invalid:
return "Invalid proxy URI";
default:
return "Unknown";
}
}
};
inline const lib::error_category& get_category() {
static category instance;
return instance;
static category instance;
return instance;
}
inline lib::error_code make_error_code(error::value e) {
return lib::error_code(static_cast<int>(e), get_category());
return lib::error_code(static_cast<int>(e), get_category());
}
} // namespace error

View File

@@ -36,7 +36,7 @@
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/system/error_code.hpp>
#include <iostream>
namespace websocketpp {
@@ -52,7 +52,7 @@ template <typename config>
class endpoint : public config::socket_type {
public:
/// Type of this endpoint transport component
typedef endpoint<config> type;
typedef endpoint<config> type;
/// Type of the concurrency policy
typedef typename config::concurrency_type concurrency_type;
@@ -70,109 +70,109 @@ public:
/// Type of the connection transport component associated with this
/// endpoint transport component
typedef asio::connection<config> transport_con_type;
typedef asio::connection<config> transport_con_type;
/// Type of a shared pointer to the connection transport component
/// associated with this endpoint transport component
typedef typename transport_con_type::ptr transport_con_ptr;
/// Type of a pointer to the ASIO io_service being used
typedef boost::asio::io_service* io_service_ptr;
typedef boost::asio::io_service* io_service_ptr;
/// Type of a shared pointer to the acceptor being used
typedef lib::shared_ptr<boost::asio::ip::tcp::acceptor> acceptor_ptr;
typedef lib::shared_ptr<boost::asio::ip::tcp::acceptor> acceptor_ptr;
/// Type of a shared pointer to the resolver being used
typedef lib::shared_ptr<boost::asio::ip::tcp::resolver> resolver_ptr;
typedef lib::shared_ptr<boost::asio::ip::tcp::resolver> resolver_ptr;
// generate and manage our own io_service
explicit endpoint()
: m_external_io_service(false)
, m_state(UNINITIALIZED)
{
//std::cout << "transport::asio::endpoint constructor" << std::endl;
}
~endpoint() {
// clean up our io_service if we were initialized with an internal one.
// generate and manage our own io_service
explicit endpoint()
: m_external_io_service(false)
, m_state(UNINITIALIZED)
{
//std::cout << "transport::asio::endpoint constructor" << std::endl;
}
~endpoint() {
// clean up our io_service if we were initialized with an internal one.
m_acceptor.reset();
if (m_state != UNINITIALIZED && !m_external_io_service) {
delete m_io_service;
}
}
if (m_state != UNINITIALIZED && !m_external_io_service) {
delete m_io_service;
}
}
/// transport::asio objects are moveable but not copyable or assignable.
/// The following code sets this situation up based on whether or not we
/// have C++11 support or not
/// transport::asio objects are moveable but not copyable or assignable.
/// The following code sets this situation up based on whether or not we
/// have C++11 support or not
#ifdef _WEBSOCKETPP_DELETED_FUNCTIONS_
endpoint(const endpoint& src) = delete;
endpoint& operator= (const endpoint & rhs) = delete;
endpoint(const endpoint& src) = delete;
endpoint& operator= (const endpoint & rhs) = delete;
#else
private:
endpoint(const endpoint& src);
endpoint& operator= (const endpoint & rhs);
endpoint(const endpoint& src);
endpoint& operator= (const endpoint & rhs);
public:
#endif
#ifdef _WEBSOCKETPP_RVALUE_REFERENCES_
endpoint (endpoint&& src)
: m_io_service(src.m_io_service)
, m_external_io_service(src.m_external_io_service)
, m_acceptor(src.m_acceptor)
, m_state(src.m_state)
{
src.m_io_service = NULL;
src.m_external_io_service = false;
src.m_acceptor = NULL;
src.m_state = UNINITIALIZED;
}
endpoint& operator= (const endpoint && rhs) {
if (this != &rhs) {
m_io_service = rhs.m_io_service;
m_external_io_service = rhs.m_external_io_service;
m_acceptor = rhs.m_acceptor;
m_state = rhs.m_state;
rhs.m_io_service = NULL;
rhs.m_external_io_service = false;
rhs.m_acceptor = NULL;
rhs.m_state = UNINITIALIZED;
}
return *this;
}
endpoint (endpoint&& src)
: m_io_service(src.m_io_service)
, m_external_io_service(src.m_external_io_service)
, m_acceptor(src.m_acceptor)
, m_state(src.m_state)
{
src.m_io_service = NULL;
src.m_external_io_service = false;
src.m_acceptor = NULL;
src.m_state = UNINITIALIZED;
}
endpoint& operator= (const endpoint && rhs) {
if (this != &rhs) {
m_io_service = rhs.m_io_service;
m_external_io_service = rhs.m_external_io_service;
m_acceptor = rhs.m_acceptor;
m_state = rhs.m_state;
rhs.m_io_service = NULL;
rhs.m_external_io_service = false;
rhs.m_acceptor = NULL;
rhs.m_state = UNINITIALIZED;
}
return *this;
}
#endif
/// initialize asio transport with external io_service
/**
* Initialize the ASIO transport policy for this endpoint using the
* io_service object. asio_init must be called exactly once on any endpoint
* that uses transport::asio before it can be used.
*
* Calling init_asio shifts the internal state from UNINITIALIZED to READY
*/
void init_asio(io_service_ptr ptr) {
if (m_state != UNINITIALIZED) {
// TODO: throw invalid state
m_elog->write(log::elevel::library,
/// initialize asio transport with external io_service
/**
* Initialize the ASIO transport policy for this endpoint using the
* io_service object. asio_init must be called exactly once on any endpoint
* that uses transport::asio before it can be used.
*
* Calling init_asio shifts the internal state from UNINITIALIZED to READY
*/
void init_asio(io_service_ptr ptr) {
if (m_state != UNINITIALIZED) {
// TODO: throw invalid state
m_elog->write(log::elevel::library,
"asio::init_asio called from the wrong state");
throw;
}
m_alog->write(log::alevel::devel,"asio::init_asio");
m_io_service = ptr;
throw;
}
m_alog->write(log::alevel::devel,"asio::init_asio");
m_io_service = ptr;
m_external_io_service = true;
m_acceptor.reset(new boost::asio::ip::tcp::acceptor(*m_io_service));
m_state = READY;
}
/// Initialize asio transport with internal io_service
/**
* @see init_asio(io_service_ptr ptr)
*/
void init_asio() {
init_asio(new boost::asio::io_service());
m_acceptor.reset(new boost::asio::ip::tcp::acceptor(*m_io_service));
m_state = READY;
}
/// Initialize asio transport with internal io_service
/**
* @see init_asio(io_service_ptr ptr)
*/
void init_asio() {
init_asio(new boost::asio::io_service());
m_external_io_service = false;
}
}
/// Sets the tcp init handler
/**
* The tcp init handler is called after the tcp connection has been
@@ -185,115 +185,115 @@ public:
m_tcp_init_handler = h;
}
// listen manually
void listen(const boost::asio::ip::tcp::endpoint& e) {
if (m_state != READY) {
// TODO
// listen manually
void listen(const boost::asio::ip::tcp::endpoint& e) {
if (m_state != READY) {
// TODO
m_elog->write(log::elevel::library,
"asio::listen called from the wrong state");
throw;
}
m_alog->write(log::alevel::devel,"asio::listen");
m_acceptor->open(e.protocol());
throw;
}
m_alog->write(log::alevel::devel,"asio::listen");
m_acceptor->open(e.protocol());
m_acceptor->set_option(boost::asio::socket_base::reuse_address(true));
m_acceptor->bind(e);
m_acceptor->listen();
m_state = LISTENING;
m_alog->write(log::alevel::devel,"mark");
}
void cancel() {
if (m_state != LISTENING) {
// TODO
throw;
}
// TODO: figure out if this is a good way to stop listening.
m_acceptor->cancel();
m_acceptor->close();
}
}
void cancel() {
if (m_state != LISTENING) {
// TODO
throw;
}
// TODO: figure out if this is a good way to stop listening.
m_acceptor->cancel();
m_acceptor->close();
}
// Accept the next connection attempt via m_acceptor and assign it to con.
// callback is called
void async_accept(transport_con_ptr tcon, accept_handler callback) {
if (m_state != LISTENING) {
// TODO: throw invalid state
// Accept the next connection attempt via m_acceptor and assign it to con.
// callback is called
void async_accept(transport_con_ptr tcon, accept_handler callback) {
if (m_state != LISTENING) {
// TODO: throw invalid state
m_elog->write(log::elevel::library,
"asio::async_accept called from the wrong state");
throw;
}
throw;
}
m_alog->write(log::alevel::devel, "asio::async_accept");
// TEMP
m_acceptor->async_accept(
tcon->get_raw_socket(),
lib::bind(
&type::handle_accept,
this,
tcon->get_handle(),
callback,
lib::placeholders::_1
)
);
}
// TEMP
m_acceptor->async_accept(
tcon->get_raw_socket(),
lib::bind(
&type::handle_accept,
this,
tcon->get_handle(),
callback,
lib::placeholders::_1
)
);
}
/// wraps the run method of the internal io_service object
std::size_t run() {
return m_io_service->run();
}
/// wraps the stop method of the internal io_service object
void stop() {
m_io_service->stop();
}
/// wraps the poll method of the internal io_service object
std::size_t poll() {
return m_io_service->poll();
}
/// wraps the poll_one method of the internal io_service object
std::size_t poll_one() {
return m_io_service->poll_one();
}
/// wraps the reset method of the internal io_service object
void reset() {
m_io_service->reset();
}
/// wraps the stopped method of the internal io_service object
bool stopped() const {
return m_io_service->stopped();
}
/// wraps the run method of the internal io_service object
std::size_t run() {
return m_io_service->run();
}
/// wraps the stop method of the internal io_service object
void stop() {
m_io_service->stop();
}
/// wraps the poll method of the internal io_service object
std::size_t poll() {
return m_io_service->poll();
}
/// wraps the poll_one method of the internal io_service object
std::size_t poll_one() {
return m_io_service->poll_one();
}
/// wraps the reset method of the internal io_service object
void reset() {
m_io_service->reset();
}
/// wraps the stopped method of the internal io_service object
bool stopped() const {
return m_io_service->stopped();
}
// convenience methods
template <typename InternetProtocol>
// convenience methods
template <typename InternetProtocol>
void listen(const InternetProtocol &internet_protocol, uint16_t port) {
boost::asio::ip::tcp::endpoint e(internet_protocol, port);
listen(e);
}
void listen(uint16_t port) {
listen(boost::asio::ip::tcp::v6(), port);
}
void listen(const std::string &host, const std::string &service) {
boost::asio::ip::tcp::resolver resolver(*m_io_service);
boost::asio::ip::tcp::resolver::query query(host, service);
boost::asio::ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
boost::asio::ip::tcp::resolver::iterator end;
if (endpoint_iterator == end) {
throw std::invalid_argument("Can't resolve host/service to listen");
}
listen(*endpoint_iterator);
}
typedef lib::shared_ptr<boost::asio::deadline_timer> timer_ptr;
void listen(uint16_t port) {
listen(boost::asio::ip::tcp::v6(), port);
}
void listen(const std::string &host, const std::string &service) {
boost::asio::ip::tcp::resolver resolver(*m_io_service);
boost::asio::ip::tcp::resolver::query query(host, service);
boost::asio::ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
boost::asio::ip::tcp::resolver::iterator end;
if (endpoint_iterator == end) {
throw std::invalid_argument("Can't resolve host/service to listen");
}
listen(*endpoint_iterator);
}
typedef lib::shared_ptr<boost::asio::deadline_timer> timer_ptr;
timer_ptr set_timer(long duration, timer_handler handler) {
timer_ptr timer(new boost::asio::deadline_timer(*m_io_service));
@@ -318,7 +318,7 @@ public:
}
boost::asio::io_service& get_io_service() {
return *m_io_service;
return *m_io_service;
}
bool is_secure() const {
@@ -340,22 +340,22 @@ protected:
m_alog = a;
}
void handle_accept(connection_hdl hdl, accept_handler callback,
void handle_accept(connection_hdl hdl, accept_handler callback,
const boost::system::error_code& error)
{
if (error) {
//con->terminate();
// TODO: Better translation of errors at this point
callback(hdl,make_error_code(error::pass_through));
return;
}
//con->start();
callback(hdl,lib::error_code());
}
/// Initiate a new connection
// TODO: there have to be some more failure conditions here
if (error) {
//con->terminate();
// TODO: Better translation of errors at this point
callback(hdl,make_error_code(error::pass_through));
return;
}
//con->start();
callback(hdl,lib::error_code());
}
/// Initiate a new connection
// TODO: there have to be some more failure conditions here
void async_connect(transport_con_ptr tcon, uri_ptr u, connect_handler cb) {
using namespace boost::asio::ip;
@@ -409,18 +409,18 @@ protected:
const boost::system::error_code& ec,
boost::asio::ip::tcp::resolver::iterator iterator)
{
if (ec) {
//con->terminate();
// TODO: Better translation of errors at this point
std::stringstream s;
if (ec) {
//con->terminate();
// TODO: Better translation of errors at this point
std::stringstream s;
s << "asio async_resolve error::pass_through: "
<< "Original Error: " << ec << " (" << ec.message() << ")";
m_elog->write(log::elevel::info,s.str());
callback(tcon->get_handle(),make_error_code(error::pass_through));
return;
}
boost::asio::async_connect(
callback(tcon->get_handle(),make_error_code(error::pass_through));
return;
}
boost::asio::async_connect(
tcon->get_raw_socket(),
iterator,
lib::bind(
@@ -428,35 +428,35 @@ protected:
this, // shared from this?
tcon,
callback,
lib::placeholders::_1
lib::placeholders::_1
)
);
}
}
void handle_connect(transport_con_ptr tcon, connect_handler callback,
const boost::system::error_code& ec)
{
if (ec) {
//con->terminate();
// TODO: Better translation of errors at this point
std::stringstream s;
if (ec) {
//con->terminate();
// TODO: Better translation of errors at this point
std::stringstream s;
s << "asio async_connect error::pass_through: "
<< "Original Error: " << ec << " (" << ec.message() << ")";
m_elog->write(log::elevel::info,s.str());
callback(tcon->get_handle(),make_error_code(error::pass_through));
return;
}
callback(tcon->get_handle(),lib::error_code());
}
bool is_listening() const {
return (m_state == LISTENING);
}
/// Initialize a connection
/**
* init is called by an endpoint once for each newly created connection.
callback(tcon->get_handle(),make_error_code(error::pass_through));
return;
}
callback(tcon->get_handle(),lib::error_code());
}
bool is_listening() const {
return (m_state == LISTENING);
}
/// Initialize a connection
/**
* init is called by an endpoint once for each newly created connection.
* It's purpose is to give the transport policy the chance to perform any
* transport specific initialization that couldn't be done via the default
* constructor.
@@ -464,8 +464,8 @@ protected:
* @param tcon A pointer to the transport portion of the connection.
*
* @return A status code indicating the success or failure of the operation
*/
lib::error_code init(transport_con_ptr tcon) {
*/
lib::error_code init(transport_con_ptr tcon) {
m_alog->write(log::alevel::devel, "transport::asio::init");
// Initialize the connection socket component
@@ -474,34 +474,34 @@ protected:
lib::error_code ec;
ec = tcon->init_asio(m_io_service);
if (ec) {return ec;}
ec = tcon->init_asio(m_io_service);
if (ec) {return ec;}
tcon->set_tcp_init_handler(m_tcp_init_handler);
return lib::error_code();
}
}
private:
enum state {
UNINITIALIZED = 0,
READY = 1,
LISTENING = 2
};
enum state {
UNINITIALIZED = 0,
READY = 1,
LISTENING = 2
};
// Handlers
tcp_init_handler m_tcp_init_handler;
// Network Resources
io_service_ptr m_io_service;
bool m_external_io_service;
acceptor_ptr m_acceptor;
resolver_ptr m_resolver;
// Network Resources
io_service_ptr m_io_service;
bool m_external_io_service;
acceptor_ptr m_acceptor;
resolver_ptr m_resolver;
elog_type* m_elog;
alog_type* m_alog;
// Transport state
state m_state;
// Transport state
state m_state;
};
} // namespace asio

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Peter Thorson. All rights reserved.
* Copyright (c) 2013, 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:
@@ -109,39 +109,39 @@ enum value {
class category : public lib::error_category {
public:
category() {}
category() {}
const char *name() const _WEBSOCKETPP_NOEXCEPT_TOKEN_ {
return "websocketpp.transport";
}
std::string message(int value) const {
switch(value) {
case general:
return "Generic transport policy error";
case pass_through:
return "Underlying Transport Error";
case invalid_num_bytes:
return "async_read_at_least call requested more bytes than buffer can store";
case operation_aborted:
return "The operation was aborted";
case operation_not_supported:
return "The operation is not supported by this transport";
case eof:
return "End of File";
default:
return "Unknown";
}
}
const char *name() const _WEBSOCKETPP_NOEXCEPT_TOKEN_ {
return "websocketpp.transport";
}
std::string message(int value) const {
switch(value) {
case general:
return "Generic transport policy error";
case pass_through:
return "Underlying Transport Error";
case invalid_num_bytes:
return "async_read_at_least call requested more bytes than buffer can store";
case operation_aborted:
return "The operation was aborted";
case operation_not_supported:
return "The operation is not supported by this transport";
case eof:
return "End of File";
default:
return "Unknown";
}
}
};
inline const lib::error_category& get_category() {
static category instance;
return instance;
static category instance;
return instance;
}
inline lib::error_code make_error_code(error::value e) {
return lib::error_code(static_cast<int>(e), get_category());
return lib::error_code(static_cast<int>(e), get_category());
}
} // namespace error

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Peter Thorson. All rights reserved.
* Copyright (c) 2013, 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:
@@ -59,37 +59,37 @@ enum value {
class category : public lib::error_category {
public:
category() {}
category() {}
const char *name() const _WEBSOCKETPP_NOEXCEPT_TOKEN_ {
return "websocketpp.transport.iostream";
}
std::string message(int value) const {
switch(value) {
case general:
return "Generic iostream transport policy error";
case invalid_num_bytes:
return "async_read_at_least call requested more bytes than buffer can store";
case double_read:
return "Async read already in progress";
case output_stream_required:
return "An output stream to be set before async_write can be used";
case bad_stream:
return "A stream operation returned ios::bad";
default:
return "Unknown";
}
}
const char *name() const _WEBSOCKETPP_NOEXCEPT_TOKEN_ {
return "websocketpp.transport.iostream";
}
std::string message(int value) const {
switch(value) {
case general:
return "Generic iostream transport policy error";
case invalid_num_bytes:
return "async_read_at_least call requested more bytes than buffer can store";
case double_read:
return "Async read already in progress";
case output_stream_required:
return "An output stream to be set before async_write can be used";
case bad_stream:
return "A stream operation returned ios::bad";
default:
return "Unknown";
}
}
};
inline const lib::error_category& get_category() {
static category instance;
return instance;
static category instance;
return instance;
}
inline lib::error_code make_error_code(error::value e) {
return lib::error_code(static_cast<int>(e), get_category());
return lib::error_code(static_cast<int>(e), get_category());
}
} // namespace error

View File

@@ -46,10 +46,10 @@ template <typename config>
class connection {
public:
/// Type of this connection transport component
typedef connection<config> type;
typedef connection<config> type;
/// Type of a shared pointer to this connection transport component
typedef lib::shared_ptr<type> ptr;
/// transport concurrency policy
typedef typename config::concurrency_type concurrency_type;
/// Type of this transport's access logging policy
@@ -58,227 +58,227 @@ public:
typedef typename config::elog_type elog_type;
// Concurrency policy types
typedef typename concurrency_type::scoped_lock_type scoped_lock_type;
typedef typename concurrency_type::mutex_type mutex_type;
explicit connection(bool is_server, alog_type& alog, elog_type& elog)
: m_output_stream(NULL)
, m_reading(false)
, m_is_server(is_server)
, m_alog(alog)
, m_elog(elog)
{
typedef typename concurrency_type::scoped_lock_type scoped_lock_type;
typedef typename concurrency_type::mutex_type mutex_type;
explicit connection(bool is_server, alog_type& alog, elog_type& elog)
: m_output_stream(NULL)
, m_reading(false)
, m_is_server(is_server)
, m_alog(alog)
, m_elog(elog)
{
m_alog.write(log::alevel::devel,"iostream con transport constructor");
}
/// Register a std::ostream with the transport for writing output
/**
* Register a std::ostream with the transport. All future writes will be
* done to this output stream.
*
* @param o A pointer to the ostream to use for output.
*/
void register_ostream(std::ostream* o) {
// TODO: lock transport state?
scoped_lock_type lock(m_read_mutex);
m_output_stream = o;
}
/// Overloaded stream input operator
/**
* Attempts to read input from the given stream into the transport. Bytes
* will be extracted from the input stream to fullfill any pending reads.
* Input in this manner will only read until the current read buffer has
* been filled. Then it will signal the library to process the input. If the
* library's input handler adds a new async_read, additional bytes will be
* read, otherwise the input operation will end.
*
* When this function returns one of the following conditions is true:
* - There is no outstanding read operation
* - There are no more bytes avaliable in the input stream
*
* You can use tellg() on the input stream to determine if all of the input
* bytes were read or not.
*
* If there is no pending read operation when the input method is called, it
* will return immediately and tellg() will not have changed.
*/
friend std::istream& operator>> (std::istream &in, type &t) {
// this serializes calls to external read.
scoped_lock_type lock(t.m_read_mutex);
t.read(in);
return in;
}
/// Manual input supply
/**
* Copies bytes from buf into WebSocket++'s input buffers. Bytes will be
* copied from the supplied buffer to fullfull any pending library reads. It
* will return the number of bytes successfully processed. If there are no
* pending reads readsome will return immediately. Not all of the bytes may
* be able to be read in one call
*/
size_t readsome(const char *buf, size_t len) {
// this serializes calls to external read.
scoped_lock_type lock(m_read_mutex);
return this->readsome_impl(buf,len);
}
/// Tests whether or not the underlying transport is secure
/**
* iostream transport will return false always because it has no information
* about the ultimate remote endpoint. This may or may not be accurate
* depending on the real source of bytes being input.
*
* TODO: allow user settable is_secure flag if this seems useful
*
* @return Whether or not the underlying transport is secure
*/
bool is_secure() const {
return false;
}
/// Get the remote endpoint address
/**
* The iostream transport has no information about the ultimate remote
* endpoint. It will return the string "iostream transport". To indicate
* this.
*
* TODO: allow user settable remote endpoint addresses if this seems useful
*
* @return A string identifying the address of the remote endpoint
*/
std::string get_remote_endpoint() const {
return "iostream transport";
}
/// Get the connection handle
}
/// Register a std::ostream with the transport for writing output
/**
* Register a std::ostream with the transport. All future writes will be
* done to this output stream.
*
* @param o A pointer to the ostream to use for output.
*/
void register_ostream(std::ostream* o) {
// TODO: lock transport state?
scoped_lock_type lock(m_read_mutex);
m_output_stream = o;
}
/// Overloaded stream input operator
/**
* Attempts to read input from the given stream into the transport. Bytes
* will be extracted from the input stream to fullfill any pending reads.
* Input in this manner will only read until the current read buffer has
* been filled. Then it will signal the library to process the input. If the
* library's input handler adds a new async_read, additional bytes will be
* read, otherwise the input operation will end.
*
* When this function returns one of the following conditions is true:
* - There is no outstanding read operation
* - There are no more bytes avaliable in the input stream
*
* You can use tellg() on the input stream to determine if all of the input
* bytes were read or not.
*
* If there is no pending read operation when the input method is called, it
* will return immediately and tellg() will not have changed.
*/
friend std::istream& operator>> (std::istream &in, type &t) {
// this serializes calls to external read.
scoped_lock_type lock(t.m_read_mutex);
t.read(in);
return in;
}
/// Manual input supply
/**
* Copies bytes from buf into WebSocket++'s input buffers. Bytes will be
* copied from the supplied buffer to fullfull any pending library reads. It
* will return the number of bytes successfully processed. If there are no
* pending reads readsome will return immediately. Not all of the bytes may
* be able to be read in one call
*/
size_t readsome(const char *buf, size_t len) {
// this serializes calls to external read.
scoped_lock_type lock(m_read_mutex);
return this->readsome_impl(buf,len);
}
/// Tests whether or not the underlying transport is secure
/**
* iostream transport will return false always because it has no information
* about the ultimate remote endpoint. This may or may not be accurate
* depending on the real source of bytes being input.
*
* TODO: allow user settable is_secure flag if this seems useful
*
* @return Whether or not the underlying transport is secure
*/
bool is_secure() const {
return false;
}
/// Get the remote endpoint address
/**
* The iostream transport has no information about the ultimate remote
* endpoint. It will return the string "iostream transport". To indicate
* this.
*
* TODO: allow user settable remote endpoint addresses if this seems useful
*
* @return A string identifying the address of the remote endpoint
*/
std::string get_remote_endpoint() const {
return "iostream transport";
}
/// Get the connection handle
connection_hdl get_handle() const {
return m_connection_hdl;
}
protected:
void init(init_handler callback) {
void init(init_handler callback) {
m_alog.write(log::alevel::devel,"iostream connection init");
callback(lib::error_code());
}
/// Initiate an async_read for at least num_bytes bytes into buf
/**
* Initiates an async_read request for at least num_bytes bytes. The input
* will be read into buf. A maximum of len bytes will be input. When the
* operation is complete, handler will be called with the status and number
* of bytes read.
*
* This method may or may not call handler from within the initial call. The
* application should be prepared to accept either.
*
* The application should never call this method a second time before it has
* been called back for the first read. If this is done, the second read
* will be called back immediately with a double_read error.
*
* If num_bytes or len are zero handler will be called back immediately
* indicating success.
*
* @param num_bytes Don't call handler until at least this many bytes have
* been read.
*
* @param buf The buffer to read bytes into
*
* @param len The size of buf. At maximum, this many bytes will be read.
*
* @param handler The callback to invoke when the operation is complete or
* ends in an error
*/
void async_read_at_least(size_t num_bytes, char *buf, size_t len,
read_handler handler)
{
callback(lib::error_code());
}
/// Initiate an async_read for at least num_bytes bytes into buf
/**
* Initiates an async_read request for at least num_bytes bytes. The input
* will be read into buf. A maximum of len bytes will be input. When the
* operation is complete, handler will be called with the status and number
* of bytes read.
*
* This method may or may not call handler from within the initial call. The
* application should be prepared to accept either.
*
* The application should never call this method a second time before it has
* been called back for the first read. If this is done, the second read
* will be called back immediately with a double_read error.
*
* If num_bytes or len are zero handler will be called back immediately
* indicating success.
*
* @param num_bytes Don't call handler until at least this many bytes have
* been read.
*
* @param buf The buffer to read bytes into
*
* @param len The size of buf. At maximum, this many bytes will be read.
*
* @param handler The callback to invoke when the operation is complete or
* ends in an error
*/
void async_read_at_least(size_t num_bytes, char *buf, size_t len,
read_handler handler)
{
std::stringstream s;
s << "iostream_con async_read_at_least: " << num_bytes;
m_alog.write(log::alevel::devel,s.str());
if (num_bytes > len) {
handler(make_error_code(error::invalid_num_bytes),size_t(0));
return;
}
if (m_reading == true) {
handler(make_error_code(error::double_read),size_t(0));
return;
}
if (num_bytes == 0 || len == 0) {
handler(lib::error_code(),size_t(0));
return;
}
m_buf = buf;
m_len = len;
m_bytes_needed = num_bytes;
m_read_handler = handler;
m_cursor = 0;
m_reading = true;
}
/// Asyncronous Transport Write
/**
* Write len bytes in buf to the output stream. Call handler to report
* success or failure. handler may or may not be called during async_write,
* but it must be safe for this to happen.
*
* Will return 0 on success. Other possible errors (not exhaustive)
* output_stream_required: No output stream was registered to write to
* bad_stream: a ostream pass through error
*
* @param buf buffer to read bytes from
* @param len number of bytes to write
* @param handler Callback to invoke with operation status.
*/
void async_write(const char* buf, size_t len, write_handler handler) {
if (num_bytes > len) {
handler(make_error_code(error::invalid_num_bytes),size_t(0));
return;
}
if (m_reading == true) {
handler(make_error_code(error::double_read),size_t(0));
return;
}
if (num_bytes == 0 || len == 0) {
handler(lib::error_code(),size_t(0));
return;
}
m_buf = buf;
m_len = len;
m_bytes_needed = num_bytes;
m_read_handler = handler;
m_cursor = 0;
m_reading = true;
}
/// Asyncronous Transport Write
/**
* Write len bytes in buf to the output stream. Call handler to report
* success or failure. handler may or may not be called during async_write,
* but it must be safe for this to happen.
*
* Will return 0 on success. Other possible errors (not exhaustive)
* output_stream_required: No output stream was registered to write to
* bad_stream: a ostream pass through error
*
* @param buf buffer to read bytes from
* @param len number of bytes to write
* @param handler Callback to invoke with operation status.
*/
void async_write(const char* buf, size_t len, write_handler handler) {
m_alog.write(log::alevel::devel,"iostream_con async_write");
// TODO: lock transport state?
if (!m_output_stream) {
handler(make_error_code(error::output_stream_required));
return;
}
m_output_stream->write(buf,len);
if (m_output_stream->bad()) {
handler(make_error_code(error::bad_stream));
} else {
handler(lib::error_code());
}
}
// TODO: lock transport state?
if (!m_output_stream) {
handler(make_error_code(error::output_stream_required));
return;
}
m_output_stream->write(buf,len);
if (m_output_stream->bad()) {
handler(make_error_code(error::bad_stream));
} else {
handler(lib::error_code());
}
}
/// Asyncronous Transport Write (scatter-gather)
/**
* Write a sequence of buffers to the output stream. Call handler to report
* success or failure. handler may or may not be called during async_write,
* but it must be safe for this to happen.
*
* Will return 0 on success. Other possible errors (not exhaustive)
* output_stream_required: No output stream was registered to write to
* bad_stream: a ostream pass through error
*
* @param bufs vector of buffers to write
* @param handler Callback to invoke with operation status.
*/
/**
* Write a sequence of buffers to the output stream. Call handler to report
* success or failure. handler may or may not be called during async_write,
* but it must be safe for this to happen.
*
* Will return 0 on success. Other possible errors (not exhaustive)
* output_stream_required: No output stream was registered to write to
* bad_stream: a ostream pass through error
*
* @param bufs vector of buffers to write
* @param handler Callback to invoke with operation status.
*/
void async_write(const std::vector<buffer>& bufs, write_handler handler) {
m_alog.write(log::alevel::devel,"iostream_con async_write buffer list");
// TODO: lock transport state?
if (!m_output_stream) {
handler(make_error_code(error::output_stream_required));
return;
}
// TODO: lock transport state?
if (!m_output_stream) {
handler(make_error_code(error::output_stream_required));
return;
}
std::vector<buffer>::const_iterator it;
for (it = bufs.begin(); it != bufs.end(); it++) {
for (it = bufs.begin(); it != bufs.end(); it++) {
m_output_stream->write((*it).buf,(*it).len);
if (m_output_stream->bad()) {
@@ -317,10 +317,10 @@ protected:
// TODO:
}
private:
void read(std::istream &in) {
void read(std::istream &in) {
m_alog.write(log::alevel::devel,"iostream_con read");
while (in.good()) {
while (in.good()) {
if (!m_reading) {
m_elog.write(log::elevel::devel,"write while not reading");
break;
@@ -346,12 +346,12 @@ private:
m_read_handler(lib::error_code(), m_cursor);
}
}
}
size_t readsome_impl(const char * buf, size_t len) {
m_alog.write(log::alevel::devel,"iostream_con readsome");
if (!m_reading) {
}
size_t readsome_impl(const char * buf, size_t len) {
m_alog.write(log::alevel::devel,"iostream_con readsome");
if (!m_reading) {
m_elog.write(log::elevel::devel,"write while not reading");
return 0;
}
@@ -368,30 +368,30 @@ private:
}
return bytes_to_copy;
}
// Read space (Protected by m_read_mutex)
char* m_buf;
size_t m_len;
size_t m_bytes_needed;
read_handler m_read_handler;
size_t m_cursor;
// transport resources
std::ostream* m_output_stream;
}
// Read space (Protected by m_read_mutex)
char* m_buf;
size_t m_len;
size_t m_bytes_needed;
read_handler m_read_handler;
size_t m_cursor;
// transport resources
std::ostream* m_output_stream;
connection_hdl m_connection_hdl;
bool m_reading;
const bool m_is_server;
bool m_reading;
const bool m_is_server;
alog_type& m_alog;
elog_type& m_elog;
// This lock ensures that only one thread can edit read data for this
// connection. This is a very coarse lock that is basically locked all the
// time. The nature of the connection is such that it cannot be
// parallelized, the locking is here to prevent intra-connection concurrency
// in order to allow inter-connection concurrency.
mutex_type m_read_mutex;
// This lock ensures that only one thread can edit read data for this
// connection. This is a very coarse lock that is basically locked all the
// time. The nature of the connection is such that it cannot be
// parallelized, the locking is here to prevent intra-connection concurrency
// in order to allow inter-connection concurrency.
mutex_type m_read_mutex;
};

View File

@@ -57,35 +57,35 @@ public:
/// Type of this endpoint transport component's associated connection
/// transport component.
typedef iostream::connection<config> transport_con_type;
typedef iostream::connection<config> transport_con_type;
/// Type of a shared pointer to this endpoint transport component's
/// associated connection transport component
typedef typename transport_con_type::ptr transport_con_ptr;
// generate and manage our own io_service
explicit endpoint() : m_output_stream(NULL)
{
//std::cout << "transport::iostream::endpoint constructor" << std::endl;
}
void register_ostream(std::ostream* o) {
// generate and manage our own io_service
explicit endpoint() : m_output_stream(NULL)
{
//std::cout << "transport::iostream::endpoint constructor" << std::endl;
}
void register_ostream(std::ostream* o) {
m_alog->write(log::alevel::devel,"register_ostream");
m_output_stream = o;
}
/// Tests whether or not the underlying transport is secure
/**
* iostream transport will return false always because it has no information
* about the ultimate remote endpoint. This may or may not be accurate
* depending on the real source of bytes being input.
*
* TODO: allow user settable is_secure flag if this seems useful
*
* @return Whether or not the underlying transport is secure
*/
bool is_secure() const {
return false;
}
m_output_stream = o;
}
/// Tests whether or not the underlying transport is secure
/**
* iostream transport will return false always because it has no information
* about the ultimate remote endpoint. This may or may not be accurate
* depending on the real source of bytes being input.
*
* TODO: allow user settable is_secure flag if this seems useful
*
* @return Whether or not the underlying transport is secure
*/
bool is_secure() const {
return false;
}
protected:
/// Initialize logging
/**
@@ -119,12 +119,12 @@ protected:
*
* @return A status code indicating the success or failure of the operation
*/
lib::error_code init(transport_con_ptr tcon) {
tcon->register_ostream(m_output_stream);
return lib::error_code();
}
lib::error_code init(transport_con_ptr tcon) {
tcon->register_ostream(m_output_stream);
return lib::error_code();
}
private:
std::ostream* m_output_stream;
std::ostream* m_output_stream;
elog_type* m_elog;
alog_type* m_alog;
};

View File

@@ -51,7 +51,7 @@ private:
// find substring (case insensitive)
template<typename T>
typename T::const_iterator ci_find_substr( const T& str1, const T& str2,
const std::locale& loc = std::locale() )
const std::locale& loc = std::locale() )
{
return std::search( str1.begin(), str1.end(),
str2.begin(), str2.end(), my_equal<typename T::value_type>(loc) );
@@ -59,8 +59,8 @@ typename T::const_iterator ci_find_substr( const T& str1, const T& str2,
template<typename T>
typename T::const_iterator ci_find_substr(const T& str1,
const typename T::value_type* str2, typename T::size_type size,
const std::locale& loc = std::locale())
const typename T::value_type* str2, typename T::size_type size,
const std::locale& loc = std::locale())
{
return std::search( str1.begin(), str1.end(),
str2, str2+size, my_equal<typename T::value_type>(loc) );