mirror of
https://github.com/XRPLF/rippled.git
synced 2026-04-29 15:37:57 +00:00
update copyright dates and fix whitespace that doesn't match projec style
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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.
|
||||
/**
|
||||
|
||||
@@ -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.
|
||||
/**
|
||||
|
||||
@@ -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.
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace role {
|
||||
|
||||
class client {
|
||||
public:
|
||||
static bool is_server = false;
|
||||
static bool is_server = false;
|
||||
}
|
||||
|
||||
} // namespace role
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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) );
|
||||
|
||||
Reference in New Issue
Block a user