diff --git a/.gitignore b/.gitignore index 0066b58c02fc0000b037f686e4adb40f74c36576..5c995cf3c2e481c8a55d29b232114895192b6c4a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +ignored +ignored/*.* *.pdb *.idb *.log diff --git a/README.md b/README.md index 87d11321505c507f22ed70deaf01a4661684517d..6555569bd44cf7d8a4a1ad9dc4101459e285f38a 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # xxsocket -A mini simplest cross platform posix socket API wrapper, support win32 & linux & ios & android & wp8 & wp8.1-universal & win10-universal +A mini and extremely simple cross platform posix socket API wrapper, support win32 & linux & ios & android & wp8 & wp8.1-universal & win10-universal support IPv6-only network. @@ -21,3 +21,5 @@ void test_connect() } } ``` + +#pitfall: For Microsoft Visual Studio, if your project has specific precompiled header, you should include it at head of xxsocket.cpp or specific the compile option: C/C++ --> Advance -->'Forced Include File' to it(such as pch.h). \ No newline at end of file diff --git a/refs/async/sorted_multilist.hpp b/refs/async/sorted_multilist.hpp new file mode 100644 index 0000000000000000000000000000000000000000..e7e59626a7fd33287a19c03538ef3fed705a632e --- /dev/null +++ b/refs/async/sorted_multilist.hpp @@ -0,0 +1,187 @@ + + template> + class sorted_multilist + { + struct _List_entry + { + _Ty value; + _List_entry* next; +#if 1 + static void * operator new(size_t /*size*/) + { + return get_pool().get(); + } + + static void operator delete(void *p) + { + get_pool().release(p); + } + + static purelib::gc::object_pool<_List_entry>& get_pool() + { + static purelib::gc::object_pool<_List_entry> s_pool; + return s_pool; + } +#endif + }; + + public: + sorted_multilist() : _Mysize(0), _Myhead(nullptr) + { + } + + ~sorted_multilist() + { + if (!empty()) { + clear(); + } + } + + bool empty() const + { + return _Mysize == 0; + } + + size_t size() const + { + return _Mysize; + } + + void clear() + { + for (auto ptr = &_Myhead; *ptr;) + { + auto entry = *ptr; + *ptr = entry->next; + delete (entry); + } + _Myhead = nullptr; + _Mysize = 0; + } + + template + size_t remove_if(const _Fty& cond) + { + size_t count = 0; + for (auto ptr = &_Myhead; *ptr;) + { + auto entry = *ptr; + if (cond(entry->value)) { + *ptr = entry->next; + delete (entry); + ++count; + } + else { + ptr = &entry->next; + } + } + _Mysize -= count; + return count; + } + + bool remove(const _Ty& value) + { + for (auto ptr = &_Myhead; *ptr;) + { + auto entry = *ptr; + if (value == entry->value) { + *ptr = entry->next; + delete (entry); + --_Mysize; + return true; + } + else { + ptr = &entry->next; + } + } + return false; + } + + template + void foreach(const _Fty& callback) + { + for (auto ptr = _Myhead; ptr != nullptr; ptr = ptr->next) + { + callback(ptr->value); + } + } + + template + void foreach(const _Fty& callback) const + { + for (auto ptr = _Myhead; ptr != nullptr; ptr = ptr->next) + { + callback(ptr->value); + } + } + + const _Ty& front() const + { + assert(!empty()); + return _Myhead->value; + } + + _Ty& front() + { + assert(!empty()); + return _Myhead->value; + } + + void pop_front() + { + assert(!empty()); + auto deleting = _Myhead; + _Myhead = _Myhead->next; + delete deleting; + --_Mysize; + } + + void insert(const _Ty& value) + { + const _Pr comparator; + if (_Myhead != nullptr) { + auto ptr = _Myhead; + while (comparator(ptr->value, value) && ptr->next != nullptr) + { + ptr = ptr->next; + } + + // if (value == ptr->value) + // { // duplicate + // return 0; + // } + + auto newNode = _Buynode(value); + + if (ptr->next != nullptr) + { + newNode->next = ptr->next; + ptr->next = newNode; + } + else + { + ptr->next = newNode; + } + + if (comparator(value, ptr->value)) + { + std::swap(ptr->value, newNode->value); + } + } + else { + _Myhead = _Buynode(value); + } + ++_Mysize; + } + private: + _List_entry* _Buynode(const _Ty& value) + { + auto _Newnode = new _List_entry; + _Newnode->value = value; + _Newnode->next = nullptr; + return _Newnode; + } + private: + _List_entry* _Myhead; + size_t _Mysize; + }; diff --git a/refs/boost.asio/asio_auto_extract_tools/boost_asio_auto_extract.bat b/refs/boost.asio/asio_auto_extract_tools/boost_asio_auto_extract.bat index 9877e636636e5aa50efd5e27d4677baf6fd70a18..04b0178ac67ed023162831d7fb26811418d766eb 100644 --- a/refs/boost.asio/asio_auto_extract_tools/boost_asio_auto_extract.bat +++ b/refs/boost.asio/asio_auto_extract_tools/boost_asio_auto_extract.bat @@ -13,7 +13,7 @@ call "%programdir%\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" setlocal enabledelayedexpansion :L_Loop -cl /nologo /O2 /W0 /EHsc /c /I"%boost_asio_dir%" /DBOOST_ERROR_CODE_HEADER_ONLY /DBOOST_SYSTEM_NO_DEPRECATED /DBOOST_SYSTEM_NO_LIB /DBOOST_DATE_TIME_NO_LIB /DBOOST_REGEX_NO_LIB /DBOOST_ASIO_DISABLE_THREADS pseudo.cpp 1>compile_error.txt +cl /nologo /O2 /W0 /EHsc /c /I"%boost_asio_dir%" /D_WIN32 /D_DEBUG /DBOOST_ERROR_CODE_HEADER_ONLY /DBOOST_SYSTEM_NO_DEPRECATED /DBOOST_SYSTEM_NO_LIB /DBOOST_DATE_TIME_NO_LIB /DBOOST_REGEX_NO_LIB /DBOOST_ASIO_DISABLE_IOCP pseudo.cpp 1>compile_error.txt set error_code=%errorlevel% if %error_code% == 2 ( diff --git a/refs/boost.asio/asio_auto_extract_tools/pseudo.cpp b/refs/boost.asio/asio_auto_extract_tools/pseudo.cpp index 8099ea1b706760436db1a1f28ba20bc8cc722ca8..1729a7566d495e6885c0e5fc6e378f438006d8d5 100644 --- a/refs/boost.asio/asio_auto_extract_tools/pseudo.cpp +++ b/refs/boost.asio/asio_auto_extract_tools/pseudo.cpp @@ -6,4 +6,5 @@ #include #include #include +#include diff --git a/refs/boost.asio/boost/asio/detail/eventfd_select_interrupter.hpp b/refs/boost.asio/boost/asio/detail/eventfd_select_interrupter.hpp new file mode 100644 index 0000000000000000000000000000000000000000..10f1125bca77639f75bf5b9d7b48e981d80b3825 --- /dev/null +++ b/refs/boost.asio/boost/asio/detail/eventfd_select_interrupter.hpp @@ -0,0 +1,85 @@ +// +// detail/eventfd_select_interrupter.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2008 Roelof Naude (roelof.naude at gmail dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_EVENTFD_SELECT_INTERRUPTER_HPP +#define BOOST_ASIO_DETAIL_EVENTFD_SELECT_INTERRUPTER_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#if defined(BOOST_ASIO_HAS_EVENTFD) + +#include + +namespace boost { +namespace asio { +namespace detail { + +class eventfd_select_interrupter +{ +public: + // Constructor. + BOOST_ASIO_DECL eventfd_select_interrupter(); + + // Destructor. + BOOST_ASIO_DECL ~eventfd_select_interrupter(); + + // Recreate the interrupter's descriptors. Used after a fork. + BOOST_ASIO_DECL void recreate(); + + // Interrupt the select call. + BOOST_ASIO_DECL void interrupt(); + + // Reset the select interrupt. Returns true if the call was interrupted. + BOOST_ASIO_DECL bool reset(); + + // Get the read descriptor to be passed to select. + int read_descriptor() const + { + return read_descriptor_; + } + +private: + // Open the descriptors. Throws on error. + BOOST_ASIO_DECL void open_descriptors(); + + // Close the descriptors. + BOOST_ASIO_DECL void close_descriptors(); + + // The read end of a connection used to interrupt the select call. This file + // descriptor is passed to select such that when it is time to stop, a single + // 64bit value will be written on the other end of the connection and this + // descriptor will become readable. + int read_descriptor_; + + // The write end of a connection used to interrupt the select call. A single + // 64bit non-zero value may be written to this to wake up the select which is + // waiting for the other end to become readable. This descriptor will only + // differ from the read descriptor when a pipe is used. + int write_descriptor_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#if defined(BOOST_ASIO_HEADER_ONLY) +# include +#endif // defined(BOOST_ASIO_HEADER_ONLY) + +#endif // defined(BOOST_ASIO_HAS_EVENTFD) + +#endif // BOOST_ASIO_DETAIL_EVENTFD_SELECT_INTERRUPTER_HPP diff --git a/refs/boost.asio/boost/asio/detail/function.hpp b/refs/boost.asio/boost/asio/detail/function.hpp new file mode 100644 index 0000000000000000000000000000000000000000..7b42db71f82750afd9442c70a07187e1ac1b9c48 --- /dev/null +++ b/refs/boost.asio/boost/asio/detail/function.hpp @@ -0,0 +1,40 @@ +// +// detail/function.hpp +// ~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_FUNCTION_HPP +#define BOOST_ASIO_DETAIL_FUNCTION_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#if defined(BOOST_ASIO_HAS_STD_FUNCTION) +# include +#else // defined(BOOST_ASIO_HAS_STD_FUNCTION) +# include +#endif // defined(BOOST_ASIO_HAS_STD_FUNCTION) + +namespace boost { +namespace asio { +namespace detail { + +#if defined(BOOST_ASIO_HAS_STD_FUNCTION) +using std::function; +#else // defined(BOOST_ASIO_HAS_STD_FUNCTION) +using boost::function; +#endif // defined(BOOST_ASIO_HAS_STD_FUNCTION) + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // BOOST_ASIO_DETAIL_FUNCTION_HPP diff --git a/refs/boost.asio/boost/asio/detail/impl/eventfd_select_interrupter.ipp b/refs/boost.asio/boost/asio/detail/impl/eventfd_select_interrupter.ipp new file mode 100644 index 0000000000000000000000000000000000000000..7da2302d9ea3d27314bf13c9fbaa9362be649afb --- /dev/null +++ b/refs/boost.asio/boost/asio/detail/impl/eventfd_select_interrupter.ipp @@ -0,0 +1,167 @@ +// +// detail/impl/eventfd_select_interrupter.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2008 Roelof Naude (roelof.naude at gmail dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_IMPL_EVENTFD_SELECT_INTERRUPTER_IPP +#define BOOST_ASIO_DETAIL_IMPL_EVENTFD_SELECT_INTERRUPTER_IPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#if defined(BOOST_ASIO_HAS_EVENTFD) + +#include +#include +#include +#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 8 +# include +#else // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8 +# include +#endif // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8 +#include +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +eventfd_select_interrupter::eventfd_select_interrupter() +{ + open_descriptors(); +} + +void eventfd_select_interrupter::open_descriptors() +{ +#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 8 + write_descriptor_ = read_descriptor_ = syscall(__NR_eventfd, 0); + if (read_descriptor_ != -1) + { + ::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK); + ::fcntl(read_descriptor_, F_SETFD, FD_CLOEXEC); + } +#else // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8 +# if defined(EFD_CLOEXEC) && defined(EFD_NONBLOCK) + write_descriptor_ = read_descriptor_ = + ::eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK); +# else // defined(EFD_CLOEXEC) && defined(EFD_NONBLOCK) + errno = EINVAL; + write_descriptor_ = read_descriptor_ = -1; +# endif // defined(EFD_CLOEXEC) && defined(EFD_NONBLOCK) + if (read_descriptor_ == -1 && errno == EINVAL) + { + write_descriptor_ = read_descriptor_ = ::eventfd(0, 0); + if (read_descriptor_ != -1) + { + ::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK); + ::fcntl(read_descriptor_, F_SETFD, FD_CLOEXEC); + } + } +#endif // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8 + + if (read_descriptor_ == -1) + { + int pipe_fds[2]; + if (pipe(pipe_fds) == 0) + { + read_descriptor_ = pipe_fds[0]; + ::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK); + ::fcntl(read_descriptor_, F_SETFD, FD_CLOEXEC); + write_descriptor_ = pipe_fds[1]; + ::fcntl(write_descriptor_, F_SETFL, O_NONBLOCK); + ::fcntl(write_descriptor_, F_SETFD, FD_CLOEXEC); + } + else + { + boost::system::error_code ec(errno, + boost::asio::error::get_system_category()); + boost::asio::detail::throw_error(ec, "eventfd_select_interrupter"); + } + } +} + +eventfd_select_interrupter::~eventfd_select_interrupter() +{ + close_descriptors(); +} + +void eventfd_select_interrupter::close_descriptors() +{ + if (write_descriptor_ != -1 && write_descriptor_ != read_descriptor_) + ::close(write_descriptor_); + if (read_descriptor_ != -1) + ::close(read_descriptor_); +} + +void eventfd_select_interrupter::recreate() +{ + close_descriptors(); + + write_descriptor_ = -1; + read_descriptor_ = -1; + + open_descriptors(); +} + +void eventfd_select_interrupter::interrupt() +{ + uint64_t counter(1UL); + int result = ::write(write_descriptor_, &counter, sizeof(uint64_t)); + (void)result; +} + +bool eventfd_select_interrupter::reset() +{ + if (write_descriptor_ == read_descriptor_) + { + for (;;) + { + // Only perform one read. The kernel maintains an atomic counter. + uint64_t counter(0); + errno = 0; + int bytes_read = ::read(read_descriptor_, &counter, sizeof(uint64_t)); + if (bytes_read < 0 && errno == EINTR) + continue; + bool was_interrupted = (bytes_read > 0); + return was_interrupted; + } + } + else + { + for (;;) + { + // Clear all data from the pipe. + char data[1024]; + int bytes_read = ::read(read_descriptor_, data, sizeof(data)); + if (bytes_read < 0 && errno == EINTR) + continue; + bool was_interrupted = (bytes_read > 0); + while (bytes_read == sizeof(data)) + bytes_read = ::read(read_descriptor_, data, sizeof(data)); + return was_interrupted; + } + } +} + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // defined(BOOST_ASIO_HAS_EVENTFD) + +#endif // BOOST_ASIO_DETAIL_IMPL_EVENTFD_SELECT_INTERRUPTER_IPP diff --git a/refs/boost.asio/boost/asio/detail/impl/win_event.ipp b/refs/boost.asio/boost/asio/detail/impl/win_event.ipp new file mode 100644 index 0000000000000000000000000000000000000000..ccb6344399162c69975a73861f6a96e60ecf50fb --- /dev/null +++ b/refs/boost.asio/boost/asio/detail/impl/win_event.ipp @@ -0,0 +1,77 @@ +// +// detail/win_event.ipp +// ~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_IMPL_WIN_EVENT_IPP +#define BOOST_ASIO_DETAIL_IMPL_WIN_EVENT_IPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#if defined(BOOST_ASIO_WINDOWS) + +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +win_event::win_event() + : state_(0) +{ +#if defined(BOOST_ASIO_WINDOWS_APP) + events_[0] = ::CreateEventExW(0, 0, CREATE_EVENT_MANUAL_RESET, 0); +#else // defined(BOOST_ASIO_WINDOWS_APP) + events_[0] = ::CreateEventW(0, true, false, 0); +#endif // defined(BOOST_ASIO_WINDOWS_APP) + if (!events_[0]) + { + DWORD last_error = ::GetLastError(); + boost::system::error_code ec(last_error, + boost::asio::error::get_system_category()); + boost::asio::detail::throw_error(ec, "event"); + } + +#if defined(BOOST_ASIO_WINDOWS_APP) + events_[1] = ::CreateEventExW(0, 0, 0, 0); +#else // defined(BOOST_ASIO_WINDOWS_APP) + events_[1] = ::CreateEventW(0, false, false, 0); +#endif // defined(BOOST_ASIO_WINDOWS_APP) + if (!events_[1]) + { + DWORD last_error = ::GetLastError(); + ::CloseHandle(events_[0]); + boost::system::error_code ec(last_error, + boost::asio::error::get_system_category()); + boost::asio::detail::throw_error(ec, "event"); + } +} + +win_event::~win_event() +{ + ::CloseHandle(events_[0]); + ::CloseHandle(events_[1]); +} + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // defined(BOOST_ASIO_WINDOWS) + +#endif // BOOST_ASIO_DETAIL_IMPL_WIN_EVENT_IPP diff --git a/refs/boost.asio/boost/asio/detail/impl/win_mutex.ipp b/refs/boost.asio/boost/asio/detail/impl/win_mutex.ipp new file mode 100644 index 0000000000000000000000000000000000000000..56b80bede4e4ab4767f145e9928cb153db735160 --- /dev/null +++ b/refs/boost.asio/boost/asio/detail/impl/win_mutex.ipp @@ -0,0 +1,85 @@ +// +// detail/impl/win_mutex.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_IMPL_WIN_MUTEX_IPP +#define BOOST_ASIO_DETAIL_IMPL_WIN_MUTEX_IPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#if defined(BOOST_ASIO_WINDOWS) + +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +win_mutex::win_mutex() +{ + int error = do_init(); + boost::system::error_code ec(error, + boost::asio::error::get_system_category()); + boost::asio::detail::throw_error(ec, "mutex"); +} + +int win_mutex::do_init() +{ +#if defined(__MINGW32__) + // Not sure if MinGW supports structured exception handling, so for now + // we'll just call the Windows API and hope. +# if defined(UNDER_CE) + ::InitializeCriticalSection(&crit_section_); +# elif defined(BOOST_ASIO_WINDOWS_APP) + ::InitializeCriticalSectionEx(&crit_section_, 0x80000000, 0); +# else + if (!::InitializeCriticalSectionAndSpinCount(&crit_section_, 0x80000000)) + return ::GetLastError(); +# endif + return 0; +#else + __try + { +# if defined(UNDER_CE) + ::InitializeCriticalSection(&crit_section_); +# elif defined(BOOST_ASIO_WINDOWS_APP) + if (!::InitializeCriticalSectionEx(&crit_section_, 0, 0)) + return ::GetLastError(); +# else + if (!::InitializeCriticalSectionAndSpinCount(&crit_section_, 0x80000000)) + return ::GetLastError(); +# endif + } + __except(GetExceptionCode() == STATUS_NO_MEMORY + ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) + { + return ERROR_OUTOFMEMORY; + } + + return 0; +#endif +} + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // defined(BOOST_ASIO_WINDOWS) + +#endif // BOOST_ASIO_DETAIL_IMPL_WIN_MUTEX_IPP diff --git a/refs/boost.asio/boost/asio/detail/impl/win_static_mutex.ipp b/refs/boost.asio/boost/asio/detail/impl/win_static_mutex.ipp new file mode 100644 index 0000000000000000000000000000000000000000..31c72e9fbcbfaa2830324afcbe69ef523f6c3577 --- /dev/null +++ b/refs/boost.asio/boost/asio/detail/impl/win_static_mutex.ipp @@ -0,0 +1,138 @@ +// +// detail/impl/win_static_mutex.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_IMPL_WIN_STATIC_MUTEX_IPP +#define BOOST_ASIO_DETAIL_IMPL_WIN_STATIC_MUTEX_IPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#if defined(BOOST_ASIO_WINDOWS) + +#include +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +void win_static_mutex::init() +{ + int error = do_init(); + boost::system::error_code ec(error, + boost::asio::error::get_system_category()); + boost::asio::detail::throw_error(ec, "static_mutex"); +} + +int win_static_mutex::do_init() +{ + using namespace std; // For sprintf. + wchar_t mutex_name[128]; +#if defined(BOOST_ASIO_HAS_SECURE_RTL) + swprintf_s( +#else // defined(BOOST_ASIO_HAS_SECURE_RTL) + _snwprintf( +#endif // defined(BOOST_ASIO_HAS_SECURE_RTL) + mutex_name, 128, L"asio-58CCDC44-6264-4842-90C2-F3C545CB8AA7-%u-%p", + static_cast(::GetCurrentProcessId()), this); + +#if defined(BOOST_ASIO_WINDOWS_APP) + HANDLE mutex = ::CreateMutexExW(0, mutex_name, CREATE_MUTEX_INITIAL_OWNER, 0); +#else // defined(BOOST_ASIO_WINDOWS_APP) + HANDLE mutex = ::CreateMutexW(0, TRUE, mutex_name); +#endif // defined(BOOST_ASIO_WINDOWS_APP) + DWORD last_error = ::GetLastError(); + if (mutex == 0) + return ::GetLastError(); + + if (last_error == ERROR_ALREADY_EXISTS) + { +#if defined(BOOST_ASIO_WINDOWS_APP) + ::WaitForSingleObjectEx(mutex, INFINITE, false); +#else // defined(BOOST_ASIO_WINDOWS_APP) + ::WaitForSingleObject(mutex, INFINITE); +#endif // defined(BOOST_ASIO_WINDOWS_APP) + } + + if (initialised_) + { + ::ReleaseMutex(mutex); + ::CloseHandle(mutex); + return 0; + } + +#if defined(__MINGW32__) + // Not sure if MinGW supports structured exception handling, so for now + // we'll just call the Windows API and hope. +# if defined(UNDER_CE) + ::InitializeCriticalSection(&crit_section_); +# else + if (!::InitializeCriticalSectionAndSpinCount(&crit_section_, 0x80000000)) + { + last_error = ::GetLastError(); + ::ReleaseMutex(mutex); + ::CloseHandle(mutex); + return last_error; + } +# endif +#else + __try + { +# if defined(UNDER_CE) + ::InitializeCriticalSection(&crit_section_); +# elif defined(BOOST_ASIO_WINDOWS_APP) + if (!::InitializeCriticalSectionEx(&crit_section_, 0, 0)) + { + last_error = ::GetLastError(); + ::ReleaseMutex(mutex); + ::CloseHandle(mutex); + return last_error; + } +# else + if (!::InitializeCriticalSectionAndSpinCount(&crit_section_, 0x80000000)) + { + last_error = ::GetLastError(); + ::ReleaseMutex(mutex); + ::CloseHandle(mutex); + return last_error; + } +# endif + } + __except(GetExceptionCode() == STATUS_NO_MEMORY + ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) + { + ::ReleaseMutex(mutex); + ::CloseHandle(mutex); + return ERROR_OUTOFMEMORY; + } +#endif + + initialised_ = true; + ::ReleaseMutex(mutex); + ::CloseHandle(mutex); + return 0; +} + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // defined(BOOST_ASIO_WINDOWS) + +#endif // BOOST_ASIO_DETAIL_IMPL_WIN_STATIC_MUTEX_IPP diff --git a/refs/boost.asio/boost/asio/detail/impl/win_thread.ipp b/refs/boost.asio/boost/asio/detail/impl/win_thread.ipp new file mode 100644 index 0000000000000000000000000000000000000000..3cfadd7be8973312540cac7efe97f1a2994677bc --- /dev/null +++ b/refs/boost.asio/boost/asio/detail/impl/win_thread.ipp @@ -0,0 +1,145 @@ +// +// detail/impl/win_thread.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_IMPL_WIN_THREAD_IPP +#define BOOST_ASIO_DETAIL_IMPL_WIN_THREAD_IPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#if defined(BOOST_ASIO_WINDOWS) \ + && !defined(BOOST_ASIO_WINDOWS_APP) \ + && !defined(UNDER_CE) + +#include +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +win_thread::~win_thread() +{ + ::CloseHandle(thread_); + + // The exit_event_ handle is deliberately allowed to leak here since it + // is an error for the owner of an internal thread not to join() it. +} + +void win_thread::join() +{ + HANDLE handles[2] = { exit_event_, thread_ }; + ::WaitForMultipleObjects(2, handles, FALSE, INFINITE); + ::CloseHandle(exit_event_); + if (terminate_threads()) + { + ::TerminateThread(thread_, 0); + } + else + { + ::QueueUserAPC(apc_function, thread_, 0); + ::WaitForSingleObject(thread_, INFINITE); + } +} + +void win_thread::start_thread(func_base* arg, unsigned int stack_size) +{ + ::HANDLE entry_event = 0; + arg->entry_event_ = entry_event = ::CreateEventW(0, true, false, 0); + if (!entry_event) + { + DWORD last_error = ::GetLastError(); + delete arg; + boost::system::error_code ec(last_error, + boost::asio::error::get_system_category()); + boost::asio::detail::throw_error(ec, "thread.entry_event"); + } + + arg->exit_event_ = exit_event_ = ::CreateEventW(0, true, false, 0); + if (!exit_event_) + { + DWORD last_error = ::GetLastError(); + delete arg; + boost::system::error_code ec(last_error, + boost::asio::error::get_system_category()); + boost::asio::detail::throw_error(ec, "thread.exit_event"); + } + + unsigned int thread_id = 0; + thread_ = reinterpret_cast(::_beginthreadex(0, + stack_size, win_thread_function, arg, 0, &thread_id)); + if (!thread_) + { + DWORD last_error = ::GetLastError(); + delete arg; + if (entry_event) + ::CloseHandle(entry_event); + if (exit_event_) + ::CloseHandle(exit_event_); + boost::system::error_code ec(last_error, + boost::asio::error::get_system_category()); + boost::asio::detail::throw_error(ec, "thread"); + } + + if (entry_event) + { + ::WaitForSingleObject(entry_event, INFINITE); + ::CloseHandle(entry_event); + } +} + +unsigned int __stdcall win_thread_function(void* arg) +{ + win_thread::auto_func_base_ptr func = { + static_cast(arg) }; + + ::SetEvent(func.ptr->entry_event_); + + func.ptr->run(); + + // Signal that the thread has finished its work, but rather than returning go + // to sleep to put the thread into a well known state. If the thread is being + // joined during global object destruction then it may be killed using + // TerminateThread (to avoid a deadlock in DllMain). Otherwise, the SleepEx + // call will be interrupted using QueueUserAPC and the thread will shut down + // cleanly. + HANDLE exit_event = func.ptr->exit_event_; + delete func.ptr; + func.ptr = 0; + ::SetEvent(exit_event); + ::SleepEx(INFINITE, TRUE); + + return 0; +} + +#if defined(WINVER) && (WINVER < 0x0500) +void __stdcall apc_function(ULONG) {} +#else +void __stdcall apc_function(ULONG_PTR) {} +#endif + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // defined(BOOST_ASIO_WINDOWS) + // && !defined(BOOST_ASIO_WINDOWS_APP) + // && !defined(UNDER_CE) + +#endif // BOOST_ASIO_DETAIL_IMPL_WIN_THREAD_IPP diff --git a/refs/boost.asio/boost/asio/detail/impl/win_tss_ptr.ipp b/refs/boost.asio/boost/asio/detail/impl/win_tss_ptr.ipp new file mode 100644 index 0000000000000000000000000000000000000000..2ad299f832aed05e010ff0e3adef1b5ee56e82e5 --- /dev/null +++ b/refs/boost.asio/boost/asio/detail/impl/win_tss_ptr.ipp @@ -0,0 +1,59 @@ +// +// detail/impl/win_tss_ptr.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_IMPL_WIN_TSS_PTR_IPP +#define BOOST_ASIO_DETAIL_IMPL_WIN_TSS_PTR_IPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#if defined(BOOST_ASIO_WINDOWS) + +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +DWORD win_tss_ptr_create() +{ +#if defined(UNDER_CE) + enum { out_of_indexes = 0xFFFFFFFF }; +#else + enum { out_of_indexes = TLS_OUT_OF_INDEXES }; +#endif + + DWORD tss_key = ::TlsAlloc(); + if (tss_key == out_of_indexes) + { + DWORD last_error = ::GetLastError(); + boost::system::error_code ec(last_error, + boost::asio::error::get_system_category()); + boost::asio::detail::throw_error(ec, "tss"); + } + return tss_key; +} + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // defined(BOOST_ASIO_WINDOWS) + +#endif // BOOST_ASIO_DETAIL_IMPL_WIN_TSS_PTR_IPP diff --git a/refs/boost.asio/boost/asio/detail/win_event.hpp b/refs/boost.asio/boost/asio/detail/win_event.hpp new file mode 100644 index 0000000000000000000000000000000000000000..446520d9c3e3509a8530ae96c9c0824e6e2090f0 --- /dev/null +++ b/refs/boost.asio/boost/asio/detail/win_event.hpp @@ -0,0 +1,132 @@ +// +// detail/win_event.hpp +// ~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_WIN_EVENT_HPP +#define BOOST_ASIO_DETAIL_WIN_EVENT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#if defined(BOOST_ASIO_WINDOWS) + +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +class win_event + : private noncopyable +{ +public: + // Constructor. + BOOST_ASIO_DECL win_event(); + + // Destructor. + BOOST_ASIO_DECL ~win_event(); + + // Signal the event. (Retained for backward compatibility.) + template + void signal(Lock& lock) + { + this->signal_all(lock); + } + + // Signal all waiters. + template + void signal_all(Lock& lock) + { + BOOST_ASIO_ASSERT(lock.locked()); + (void)lock; + state_ |= 1; + ::SetEvent(events_[0]); + } + + // Unlock the mutex and signal one waiter. + template + void unlock_and_signal_one(Lock& lock) + { + BOOST_ASIO_ASSERT(lock.locked()); + state_ |= 1; + bool have_waiters = (state_ > 1); + lock.unlock(); + if (have_waiters) + ::SetEvent(events_[1]); + } + + // If there's a waiter, unlock the mutex and signal it. + template + bool maybe_unlock_and_signal_one(Lock& lock) + { + BOOST_ASIO_ASSERT(lock.locked()); + state_ |= 1; + if (state_ > 1) + { + lock.unlock(); + ::SetEvent(events_[1]); + return true; + } + return false; + } + + // Reset the event. + template + void clear(Lock& lock) + { + BOOST_ASIO_ASSERT(lock.locked()); + (void)lock; + ::ResetEvent(events_[0]); + state_ &= ~std::size_t(1); + } + + // Wait for the event to become signalled. + template + void wait(Lock& lock) + { + BOOST_ASIO_ASSERT(lock.locked()); + while ((state_ & 1) == 0) + { + state_ += 2; + lock.unlock(); +#if defined(BOOST_ASIO_WINDOWS_APP) + ::WaitForMultipleObjectsEx(2, events_, false, INFINITE, false); +#else // defined(BOOST_ASIO_WINDOWS_APP) + ::WaitForMultipleObjects(2, events_, false, INFINITE); +#endif // defined(BOOST_ASIO_WINDOWS_APP) + lock.lock(); + state_ -= 2; + } + } + +private: + HANDLE events_[2]; + std::size_t state_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#if defined(BOOST_ASIO_HEADER_ONLY) +# include +#endif // defined(BOOST_ASIO_HEADER_ONLY) + +#endif // defined(BOOST_ASIO_WINDOWS) + +#endif // BOOST_ASIO_DETAIL_WIN_EVENT_HPP diff --git a/refs/boost.asio/boost/asio/detail/win_fenced_block.hpp b/refs/boost.asio/boost/asio/detail/win_fenced_block.hpp new file mode 100644 index 0000000000000000000000000000000000000000..0dcae9191e5bb6848d3ad67be2585c6570282dde --- /dev/null +++ b/refs/boost.asio/boost/asio/detail/win_fenced_block.hpp @@ -0,0 +1,91 @@ +// +// detail/win_fenced_block.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_WIN_FENCED_BLOCK_HPP +#define BOOST_ASIO_DETAIL_WIN_FENCED_BLOCK_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#if defined(BOOST_ASIO_WINDOWS) && !defined(UNDER_CE) + +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +class win_fenced_block + : private noncopyable +{ +public: + enum half_t { half }; + enum full_t { full }; + + // Constructor for a half fenced block. + explicit win_fenced_block(half_t) + { + } + + // Constructor for a full fenced block. + explicit win_fenced_block(full_t) + { +#if defined(__BORLANDC__) + LONG barrier = 0; + ::InterlockedExchange(&barrier, 1); +#elif defined(BOOST_ASIO_MSVC) \ + && ((BOOST_ASIO_MSVC < 1400) || !defined(MemoryBarrier)) +# if defined(_M_IX86) +# pragma warning(push) +# pragma warning(disable:4793) + LONG barrier; + __asm { xchg barrier, eax } +# pragma warning(pop) +# endif // defined(_M_IX86) +#else + MemoryBarrier(); +#endif + } + + // Destructor. + ~win_fenced_block() + { +#if defined(__BORLANDC__) + LONG barrier = 0; + ::InterlockedExchange(&barrier, 1); +#elif defined(BOOST_ASIO_MSVC) \ + && ((BOOST_ASIO_MSVC < 1400) || !defined(MemoryBarrier)) +# if defined(_M_IX86) +# pragma warning(push) +# pragma warning(disable:4793) + LONG barrier; + __asm { xchg barrier, eax } +# pragma warning(pop) +# endif // defined(_M_IX86) +#else + MemoryBarrier(); +#endif + } +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // defined(BOOST_ASIO_WINDOWS) && !defined(UNDER_CE) + +#endif // BOOST_ASIO_DETAIL_WIN_FENCED_BLOCK_HPP diff --git a/refs/boost.asio/boost/asio/detail/win_mutex.hpp b/refs/boost.asio/boost/asio/detail/win_mutex.hpp new file mode 100644 index 0000000000000000000000000000000000000000..77d1f03cba988e063d667b6b7753e207cc7d53ed --- /dev/null +++ b/refs/boost.asio/boost/asio/detail/win_mutex.hpp @@ -0,0 +1,80 @@ +// +// detail/win_mutex.hpp +// ~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_WIN_MUTEX_HPP +#define BOOST_ASIO_DETAIL_WIN_MUTEX_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#if defined(BOOST_ASIO_WINDOWS) + +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +class win_mutex + : private noncopyable +{ +public: + typedef boost::asio::detail::scoped_lock scoped_lock; + + // Constructor. + BOOST_ASIO_DECL win_mutex(); + + // Destructor. + ~win_mutex() + { + ::DeleteCriticalSection(&crit_section_); + } + + // Lock the mutex. + void lock() + { + ::EnterCriticalSection(&crit_section_); + } + + // Unlock the mutex. + void unlock() + { + ::LeaveCriticalSection(&crit_section_); + } + +private: + // Initialisation must be performed in a separate function to the constructor + // since the compiler does not support the use of structured exceptions and + // C++ exceptions in the same function. + BOOST_ASIO_DECL int do_init(); + + ::CRITICAL_SECTION crit_section_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#if defined(BOOST_ASIO_HEADER_ONLY) +# include +#endif // defined(BOOST_ASIO_HEADER_ONLY) + +#endif // defined(BOOST_ASIO_WINDOWS) + +#endif // BOOST_ASIO_DETAIL_WIN_MUTEX_HPP diff --git a/refs/boost.asio/boost/asio/detail/win_static_mutex.hpp b/refs/boost.asio/boost/asio/detail/win_static_mutex.hpp new file mode 100644 index 0000000000000000000000000000000000000000..40cf1af921d3d4a5e6c18e4c2f0d4bf9fe49106e --- /dev/null +++ b/refs/boost.asio/boost/asio/detail/win_static_mutex.hpp @@ -0,0 +1,76 @@ +// +// detail/win_static_mutex.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_WIN_STATIC_MUTEX_HPP +#define BOOST_ASIO_DETAIL_WIN_STATIC_MUTEX_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#if defined(BOOST_ASIO_WINDOWS) + +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +struct win_static_mutex +{ + typedef boost::asio::detail::scoped_lock scoped_lock; + + // Initialise the mutex. + BOOST_ASIO_DECL void init(); + + // Initialisation must be performed in a separate function to the "public" + // init() function since the compiler does not support the use of structured + // exceptions and C++ exceptions in the same function. + BOOST_ASIO_DECL int do_init(); + + // Lock the mutex. + void lock() + { + ::EnterCriticalSection(&crit_section_); + } + + // Unlock the mutex. + void unlock() + { + ::LeaveCriticalSection(&crit_section_); + } + + bool initialised_; + ::CRITICAL_SECTION crit_section_; +}; + +#if defined(UNDER_CE) +# define BOOST_ASIO_WIN_STATIC_MUTEX_INIT { false, { 0, 0, 0, 0, 0 } } +#else // defined(UNDER_CE) +# define BOOST_ASIO_WIN_STATIC_MUTEX_INIT { false, { 0, 0, 0, 0, 0, 0 } } +#endif // defined(UNDER_CE) + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#if defined(BOOST_ASIO_HEADER_ONLY) +# include +#endif // defined(BOOST_ASIO_HEADER_ONLY) + +#endif // defined(BOOST_ASIO_WINDOWS) + +#endif // BOOST_ASIO_DETAIL_WIN_STATIC_MUTEX_HPP diff --git a/refs/boost.asio/boost/asio/detail/win_thread.hpp b/refs/boost.asio/boost/asio/detail/win_thread.hpp new file mode 100644 index 0000000000000000000000000000000000000000..1f5ba5f24579849210d0c2bb94e5983610a98b22 --- /dev/null +++ b/refs/boost.asio/boost/asio/detail/win_thread.hpp @@ -0,0 +1,145 @@ +// +// detail/win_thread.hpp +// ~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_WIN_THREAD_HPP +#define BOOST_ASIO_DETAIL_WIN_THREAD_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#if defined(BOOST_ASIO_WINDOWS) \ + && !defined(BOOST_ASIO_WINDOWS_APP) \ + && !defined(UNDER_CE) + +#include +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +BOOST_ASIO_DECL unsigned int __stdcall win_thread_function(void* arg); + +#if defined(WINVER) && (WINVER < 0x0500) +BOOST_ASIO_DECL void __stdcall apc_function(ULONG data); +#else +BOOST_ASIO_DECL void __stdcall apc_function(ULONG_PTR data); +#endif + +template +class win_thread_base +{ +public: + static bool terminate_threads() + { + return ::InterlockedExchangeAdd(&terminate_threads_, 0) != 0; + } + + static void set_terminate_threads(bool b) + { + ::InterlockedExchange(&terminate_threads_, b ? 1 : 0); + } + +private: + static long terminate_threads_; +}; + +template +long win_thread_base::terminate_threads_ = 0; + +class win_thread + : private noncopyable, + public win_thread_base +{ +public: + // Constructor. + template + win_thread(Function f, unsigned int stack_size = 0) + : thread_(0), + exit_event_(0) + { + start_thread(new func(f), stack_size); + } + + // Destructor. + BOOST_ASIO_DECL ~win_thread(); + + // Wait for the thread to exit. + BOOST_ASIO_DECL void join(); + +private: + friend BOOST_ASIO_DECL unsigned int __stdcall win_thread_function(void* arg); + +#if defined(WINVER) && (WINVER < 0x0500) + friend BOOST_ASIO_DECL void __stdcall apc_function(ULONG); +#else + friend BOOST_ASIO_DECL void __stdcall apc_function(ULONG_PTR); +#endif + + class func_base + { + public: + virtual ~func_base() {} + virtual void run() = 0; + ::HANDLE entry_event_; + ::HANDLE exit_event_; + }; + + struct auto_func_base_ptr + { + func_base* ptr; + ~auto_func_base_ptr() { delete ptr; } + }; + + template + class func + : public func_base + { + public: + func(Function f) + : f_(f) + { + } + + virtual void run() + { + f_(); + } + + private: + Function f_; + }; + + BOOST_ASIO_DECL void start_thread(func_base* arg, unsigned int stack_size); + + ::HANDLE thread_; + ::HANDLE exit_event_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#if defined(BOOST_ASIO_HEADER_ONLY) +# include +#endif // defined(BOOST_ASIO_HEADER_ONLY) + +#endif // defined(BOOST_ASIO_WINDOWS) + // && !defined(BOOST_ASIO_WINDOWS_APP) + // && !defined(UNDER_CE) + +#endif // BOOST_ASIO_DETAIL_WIN_THREAD_HPP diff --git a/refs/boost.asio/boost/asio/detail/win_tss_ptr.hpp b/refs/boost.asio/boost/asio/detail/win_tss_ptr.hpp new file mode 100644 index 0000000000000000000000000000000000000000..e104c3b3be42125d19ef6c3b306548b950e6ee76 --- /dev/null +++ b/refs/boost.asio/boost/asio/detail/win_tss_ptr.hpp @@ -0,0 +1,81 @@ +// +// detail/win_tss_ptr.hpp +// ~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_WIN_TSS_PTR_HPP +#define BOOST_ASIO_DETAIL_WIN_TSS_PTR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#if defined(BOOST_ASIO_WINDOWS) + +#include +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +// Helper function to create thread-specific storage. +BOOST_ASIO_DECL DWORD win_tss_ptr_create(); + +template +class win_tss_ptr + : private noncopyable +{ +public: + // Constructor. + win_tss_ptr() + : tss_key_(win_tss_ptr_create()) + { + } + + // Destructor. + ~win_tss_ptr() + { + ::TlsFree(tss_key_); + } + + // Get the value. + operator T*() const + { + return static_cast(::TlsGetValue(tss_key_)); + } + + // Set the value. + void operator=(T* value) + { + ::TlsSetValue(tss_key_, value); + } + +private: + // Thread-specific storage to allow unlocked access to determine whether a + // thread is a member of the pool. + DWORD tss_key_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#if defined(BOOST_ASIO_HEADER_ONLY) +# include +#endif // defined(BOOST_ASIO_HEADER_ONLY) + +#endif // defined(BOOST_ASIO_WINDOWS) + +#endif // BOOST_ASIO_DETAIL_WIN_TSS_PTR_HPP diff --git a/refs/boost.asio/boost/exception/all.hpp b/refs/boost.asio/boost/exception/all.hpp new file mode 100644 index 0000000000000000000000000000000000000000..b57b62ba7c02c9028cc44ad1e1076e3a970a190c --- /dev/null +++ b/refs/boost.asio/boost/exception/all.hpp @@ -0,0 +1,36 @@ +//Copyright (c) 2006-2008 Emil Dotchevski and Reverge Studios, Inc. + +//Distributed under the Boost Software License, Version 1.0. (See accompanying +//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef UUID_316FDA946C0D11DEA9CBAE5255D89593 +#define UUID_316FDA946C0D11DEA9CBAE5255D89593 +#if (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) +#pragma GCC system_header +#endif +#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) +#pragma warning(push,1) +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef BOOST_NO_EXCEPTIONS +#include +#include +#endif + +#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) +#pragma warning(pop) +#endif +#endif diff --git a/refs/boost.asio/boost/exception/current_exception_cast.hpp b/refs/boost.asio/boost/exception/current_exception_cast.hpp new file mode 100644 index 0000000000000000000000000000000000000000..52ea2f70bc62037e5aa4fb1a088063c9259d343c --- /dev/null +++ b/refs/boost.asio/boost/exception/current_exception_cast.hpp @@ -0,0 +1,43 @@ +//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc. + +//Distributed under the Boost Software License, Version 1.0. (See accompanying +//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef UUID_7E83C166200811DE885E826156D89593 +#define UUID_7E83C166200811DE885E826156D89593 +#if (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) +#pragma GCC system_header +#endif +#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) +#pragma warning(push,1) +#endif + +namespace +boost + { + template + inline + E * + current_exception_cast() + { + try + { + throw; + } + catch( + E & e ) + { + return &e; + } + catch( + ...) + { + return 0; + } + } + } + +#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) +#pragma warning(pop) +#endif +#endif diff --git a/refs/boost.asio/boost/exception/detail/clone_current_exception.hpp b/refs/boost.asio/boost/exception/detail/clone_current_exception.hpp new file mode 100644 index 0000000000000000000000000000000000000000..73ad950935abb18766aab0a1b856b99c19f1abc1 --- /dev/null +++ b/refs/boost.asio/boost/exception/detail/clone_current_exception.hpp @@ -0,0 +1,56 @@ +//Copyright (c) 2006-2013 Emil Dotchevski and Reverge Studios, Inc. + +//Distributed under the Boost Software License, Version 1.0. (See accompanying +//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef UUID_81522C0EB56511DFAB613DB0DFD72085 +#define UUID_81522C0EB56511DFAB613DB0DFD72085 +#if (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) +#pragma GCC system_header +#endif +#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) +#pragma warning(push,1) +#endif + +#ifdef BOOST_NO_EXCEPTIONS +# error This header requires exception handling to be enabled. +#endif + +namespace +boost + { + namespace + exception_detail + { + class clone_base; + +#ifdef BOOST_ENABLE_NON_INTRUSIVE_EXCEPTION_PTR + int clone_current_exception_non_intrusive( clone_base const * & cloned ); +#endif + + namespace + clone_current_exception_result + { + int const success=0; + int const bad_alloc=1; + int const bad_exception=2; + int const not_supported=3; + } + + inline + int + clone_current_exception( clone_base const * & cloned ) + { +#ifdef BOOST_ENABLE_NON_INTRUSIVE_EXCEPTION_PTR + return clone_current_exception_non_intrusive(cloned); +#else + return clone_current_exception_result::not_supported; +#endif + } + } + } + +#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) +#pragma warning(pop) +#endif +#endif diff --git a/refs/boost.asio/boost/exception/detail/error_info_impl.hpp b/refs/boost.asio/boost/exception/detail/error_info_impl.hpp new file mode 100644 index 0000000000000000000000000000000000000000..e71fa9275cb0fffdaeed48c1716c0f3b775dc671 --- /dev/null +++ b/refs/boost.asio/boost/exception/detail/error_info_impl.hpp @@ -0,0 +1,74 @@ +//Copyright (c) 2006-2010 Emil Dotchevski and Reverge Studios, Inc. + +//Distributed under the Boost Software License, Version 1.0. (See accompanying +//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef UUID_CE6983AC753411DDA764247956D89593 +#define UUID_CE6983AC753411DDA764247956D89593 +#if (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) +#pragma GCC system_header +#endif +#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) +#pragma warning(push,1) +#endif + +#include + +namespace +boost + { + namespace + exception_detail + { + class + error_info_base + { + public: + + virtual std::string name_value_string() const = 0; + + protected: + + virtual + ~error_info_base() throw() + { + } + }; + } + + template + class + error_info: + public exception_detail::error_info_base + { + public: + + typedef T value_type; + + error_info( value_type const & value ); + ~error_info() throw(); + + value_type const & + value() const + { + return value_; + } + + value_type & + value() + { + return value_; + } + + private: + + std::string name_value_string() const; + + value_type value_; + }; + } + +#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) +#pragma warning(pop) +#endif +#endif diff --git a/refs/boost.asio/boost/exception/detail/exception_ptr.hpp b/refs/boost.asio/boost/exception/detail/exception_ptr.hpp new file mode 100644 index 0000000000000000000000000000000000000000..4d8a809fe9324a766371eb28679c7edde3b6cce0 --- /dev/null +++ b/refs/boost.asio/boost/exception/detail/exception_ptr.hpp @@ -0,0 +1,513 @@ +//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc. + +//Distributed under the Boost Software License, Version 1.0. (See accompanying +//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef UUID_618474C2DE1511DEB74A388C56D89593 +#define UUID_618474C2DE1511DEB74A388C56D89593 +#if (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) +#pragma GCC system_header +#endif +#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) +#pragma warning(push,1) +#endif + +#include +#ifdef BOOST_NO_EXCEPTIONS +#error This header requires exception handling to be enabled. +#endif +#include +#include +#include +#include +#include +#ifndef BOOST_NO_RTTI +#include +#endif +#include +#include +#include +#include +#include + +namespace +boost + { + class exception_ptr; + BOOST_NORETURN void rethrow_exception( exception_ptr const & ); + exception_ptr current_exception(); + + class + exception_ptr + { + typedef boost::shared_ptr impl; + impl ptr_; + friend void rethrow_exception( exception_ptr const & ); + typedef exception_detail::clone_base const * (impl::*unspecified_bool_type)() const; + public: + exception_ptr() + { + } + explicit + exception_ptr( impl const & ptr ): + ptr_(ptr) + { + } + bool + operator==( exception_ptr const & other ) const + { + return ptr_==other.ptr_; + } + bool + operator!=( exception_ptr const & other ) const + { + return ptr_!=other.ptr_; + } + operator unspecified_bool_type() const + { + return ptr_?&impl::get:0; + } + }; + + template + inline + exception_ptr + copy_exception( T const & e ) + { + try + { + throw enable_current_exception(e); + } + catch( + ... ) + { + return current_exception(); + } + } + +#ifndef BOOST_NO_RTTI + typedef error_info original_exception_type; + + inline + std::string + to_string( original_exception_type const & x ) + { + return core::demangle(x.value()->name()); + } +#endif + + namespace + exception_detail + { + struct + bad_alloc_: + boost::exception, + std::bad_alloc + { + ~bad_alloc_() throw() { } + }; + + struct + bad_exception_: + boost::exception, + std::bad_exception + { + ~bad_exception_() throw() { } + }; + + template + exception_ptr + get_static_exception_object() + { + Exception ba; + exception_detail::clone_impl c(ba); +#ifndef BOOST_EXCEPTION_DISABLE + c << + throw_function(BOOST_CURRENT_FUNCTION) << + throw_file(__FILE__) << + throw_line(__LINE__); +#endif + static exception_ptr ep(shared_ptr(new exception_detail::clone_impl(c))); + return ep; + } + + template + struct + exception_ptr_static_exception_object + { + static exception_ptr const e; + }; + + template + exception_ptr const + exception_ptr_static_exception_object:: + e = get_static_exception_object(); + } + +#if defined(__GNUC__) +# if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4) +# pragma GCC visibility push (default) +# endif +#endif + class + unknown_exception: + public boost::exception, + public std::exception + { + public: + + unknown_exception() + { + } + + explicit + unknown_exception( std::exception const & e ) + { + add_original_type(e); + } + + explicit + unknown_exception( boost::exception const & e ): + boost::exception(e) + { + add_original_type(e); + } + + ~unknown_exception() throw() + { + } + + private: + + template + void + add_original_type( E const & e ) + { +#ifndef BOOST_NO_RTTI + (*this) << original_exception_type(&typeid(e)); +#endif + } + }; +#if defined(__GNUC__) +# if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4) +# pragma GCC visibility pop +# endif +#endif + + namespace + exception_detail + { + template + class + current_exception_std_exception_wrapper: + public T, + public boost::exception + { + public: + + explicit + current_exception_std_exception_wrapper( T const & e1 ): + T(e1) + { + add_original_type(e1); + } + + current_exception_std_exception_wrapper( T const & e1, boost::exception const & e2 ): + T(e1), + boost::exception(e2) + { + add_original_type(e1); + } + + ~current_exception_std_exception_wrapper() throw() + { + } + + private: + + template + void + add_original_type( E const & e ) + { +#ifndef BOOST_NO_RTTI + (*this) << original_exception_type(&typeid(e)); +#endif + } + }; + +#ifdef BOOST_NO_RTTI + template + boost::exception const * + get_boost_exception( T const * ) + { + try + { + throw; + } + catch( + boost::exception & x ) + { + return &x; + } + catch(...) + { + return 0; + } + } +#else + template + boost::exception const * + get_boost_exception( T const * x ) + { + return dynamic_cast(x); + } +#endif + + template + inline + exception_ptr + current_exception_std_exception( T const & e1 ) + { + if( boost::exception const * e2 = get_boost_exception(&e1) ) + return boost::copy_exception(current_exception_std_exception_wrapper(e1,*e2)); + else + return boost::copy_exception(current_exception_std_exception_wrapper(e1)); + } + + inline + exception_ptr + current_exception_unknown_exception() + { + return boost::copy_exception(unknown_exception()); + } + + inline + exception_ptr + current_exception_unknown_boost_exception( boost::exception const & e ) + { + return boost::copy_exception(unknown_exception(e)); + } + + inline + exception_ptr + current_exception_unknown_std_exception( std::exception const & e ) + { + if( boost::exception const * be = get_boost_exception(&e) ) + return current_exception_unknown_boost_exception(*be); + else + return boost::copy_exception(unknown_exception(e)); + } + + inline + exception_ptr + current_exception_impl() + { + exception_detail::clone_base const * e=0; + switch( + exception_detail::clone_current_exception(e) ) + { + case exception_detail::clone_current_exception_result:: + success: + { + BOOST_ASSERT(e!=0); + return exception_ptr(shared_ptr(e)); + } + case exception_detail::clone_current_exception_result:: + bad_alloc: + { + BOOST_ASSERT(!e); + return exception_detail::exception_ptr_static_exception_object::e; + } + case exception_detail::clone_current_exception_result:: + bad_exception: + { + BOOST_ASSERT(!e); + return exception_detail::exception_ptr_static_exception_object::e; + } + default: + BOOST_ASSERT(0); + case exception_detail::clone_current_exception_result:: + not_supported: + { + BOOST_ASSERT(!e); + try + { + throw; + } + catch( + exception_detail::clone_base & e ) + { + return exception_ptr(shared_ptr(e.clone())); + } + catch( + std::domain_error & e ) + { + return exception_detail::current_exception_std_exception(e); + } + catch( + std::invalid_argument & e ) + { + return exception_detail::current_exception_std_exception(e); + } + catch( + std::length_error & e ) + { + return exception_detail::current_exception_std_exception(e); + } + catch( + std::out_of_range & e ) + { + return exception_detail::current_exception_std_exception(e); + } + catch( + std::logic_error & e ) + { + return exception_detail::current_exception_std_exception(e); + } + catch( + std::range_error & e ) + { + return exception_detail::current_exception_std_exception(e); + } + catch( + std::overflow_error & e ) + { + return exception_detail::current_exception_std_exception(e); + } + catch( + std::underflow_error & e ) + { + return exception_detail::current_exception_std_exception(e); + } + catch( + std::ios_base::failure & e ) + { + return exception_detail::current_exception_std_exception(e); + } + catch( + std::runtime_error & e ) + { + return exception_detail::current_exception_std_exception(e); + } + catch( + std::bad_alloc & e ) + { + return exception_detail::current_exception_std_exception(e); + } +#ifndef BOOST_NO_TYPEID + catch( + std::bad_cast & e ) + { + return exception_detail::current_exception_std_exception(e); + } + catch( + std::bad_typeid & e ) + { + return exception_detail::current_exception_std_exception(e); + } +#endif + catch( + std::bad_exception & e ) + { + return exception_detail::current_exception_std_exception(e); + } + catch( + std::exception & e ) + { + return exception_detail::current_exception_unknown_std_exception(e); + } + catch( + boost::exception & e ) + { + return exception_detail::current_exception_unknown_boost_exception(e); + } + catch( + ... ) + { + return exception_detail::current_exception_unknown_exception(); + } + } + } + } + } + + inline + exception_ptr + current_exception() + { + exception_ptr ret; + try + { + ret=exception_detail::current_exception_impl(); + } + catch( + std::bad_alloc & ) + { + ret=exception_detail::exception_ptr_static_exception_object::e; + } + catch( + ... ) + { + ret=exception_detail::exception_ptr_static_exception_object::e; + } + BOOST_ASSERT(ret); + return ret; + } + + BOOST_NORETURN + inline + void + rethrow_exception( exception_ptr const & p ) + { + BOOST_ASSERT(p); + p.ptr_->rethrow(); + BOOST_ASSERT(0); + #if defined(UNDER_CE) + // some CE platforms don't define ::abort() + exit(-1); + #else + abort(); + #endif + } + + inline + std::string + diagnostic_information( exception_ptr const & p, bool verbose=true ) + { + if( p ) + try + { + rethrow_exception(p); + } + catch( + ... ) + { + return current_exception_diagnostic_information(verbose); + } + return ""; + } + + inline + std::string + to_string( exception_ptr const & p ) + { + std::string s='\n'+diagnostic_information(p); + std::string padding(" "); + std::string r; + bool f=false; + for( std::string::const_iterator i=s.begin(),e=s.end(); i!=e; ++i ) + { + if( f ) + r+=padding; + char c=*i; + r+=c; + f=(c=='\n'); + } + return r; + } + } + +#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) +#pragma warning(pop) +#endif +#endif diff --git a/refs/boost.asio/boost/exception/detail/is_output_streamable.hpp b/refs/boost.asio/boost/exception/detail/is_output_streamable.hpp new file mode 100644 index 0000000000000000000000000000000000000000..12a47bdb647e4f514b3bbf29c3f7f7da17c69661 --- /dev/null +++ b/refs/boost.asio/boost/exception/detail/is_output_streamable.hpp @@ -0,0 +1,60 @@ +//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc. + +//Distributed under the Boost Software License, Version 1.0. (See accompanying +//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef UUID_898984B4076411DD973EDFA055D89593 +#define UUID_898984B4076411DD973EDFA055D89593 +#if (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) +#pragma GCC system_header +#endif +#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) +#pragma warning(push,1) +#endif + +#include + +namespace +boost + { + namespace + to_string_detail + { + struct + partial_ordering_helper1 + { + template + partial_ordering_helper1( std::basic_ostream & ); + }; + + struct + partial_ordering_helper2 + { + template + partial_ordering_helper2( T const & ); + }; + + char operator<<( partial_ordering_helper1, partial_ordering_helper2 ); + + template + struct + is_output_streamable_impl + { + static std::basic_ostream & f(); + static T const & g(); + enum e { value=1!=(sizeof(f()< > + struct + is_output_streamable + { + enum e { value=to_string_detail::is_output_streamable_impl::value }; + }; + } + +#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) +#pragma warning(pop) +#endif +#endif diff --git a/refs/boost.asio/boost/exception/detail/object_hex_dump.hpp b/refs/boost.asio/boost/exception/detail/object_hex_dump.hpp new file mode 100644 index 0000000000000000000000000000000000000000..8d28153235ec6b12639c3311db80580ad308159c --- /dev/null +++ b/refs/boost.asio/boost/exception/detail/object_hex_dump.hpp @@ -0,0 +1,50 @@ +//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc. + +//Distributed under the Boost Software License, Version 1.0. (See accompanying +//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef UUID_6F463AC838DF11DDA3E6909F56D89593 +#define UUID_6F463AC838DF11DDA3E6909F56D89593 +#if (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) +#pragma GCC system_header +#endif +#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) +#pragma warning(push,1) +#endif + +#include +#include +#include +#include +#include +#include + +namespace +boost + { + namespace + exception_detail + { + template + inline + std::string + object_hex_dump( T const & x, std::size_t max_size=16 ) + { + std::ostringstream s; + s << "type: " << type_name() << ", size: " << sizeof(T) << ", dump: "; + std::size_t n=sizeof(T)>max_size?max_size:sizeof(T); + s.fill('0'); + s.width(2); + unsigned char const * b=reinterpret_cast(&x); + s << std::setw(2) << std::hex << (unsigned int)*b; + for( unsigned char const * e=b+n; ++b!=e; ) + s << " " << std::setw(2) << std::hex << (unsigned int)*b; + return s.str(); + } + } + } + +#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) +#pragma warning(pop) +#endif +#endif diff --git a/refs/boost.asio/boost/exception/detail/type_info.hpp b/refs/boost.asio/boost/exception/detail/type_info.hpp new file mode 100644 index 0000000000000000000000000000000000000000..8361650e8c7a2ffe32ebb8aca77c6615e60f7364 --- /dev/null +++ b/refs/boost.asio/boost/exception/detail/type_info.hpp @@ -0,0 +1,81 @@ +//Copyright (c) 2006-2010 Emil Dotchevski and Reverge Studios, Inc. + +//Distributed under the Boost Software License, Version 1.0. (See accompanying +//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef UUID_C3E1741C754311DDB2834CCA55D89593 +#define UUID_C3E1741C754311DDB2834CCA55D89593 +#if (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) +#pragma GCC system_header +#endif +#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) +#pragma warning(push,1) +#endif + +#include +#include +#include +#include +#include + +namespace +boost + { + template + inline + std::string + tag_type_name() + { +#ifdef BOOST_NO_TYPEID + return BOOST_CURRENT_FUNCTION; +#else + return core::demangle(typeid(T*).name()); +#endif + } + + template + inline + std::string + type_name() + { +#ifdef BOOST_NO_TYPEID + return BOOST_CURRENT_FUNCTION; +#else + return core::demangle(typeid(T).name()); +#endif + } + + namespace + exception_detail + { + struct + type_info_ + { + core::typeinfo const * type_; + + explicit + type_info_( core::typeinfo const & type ): + type_(&type) + { + } + + friend + bool + operator<( type_info_ const & a, type_info_ const & b ) + { + return 0!=(a.type_->before(*b.type_)); + } + }; + } + } + +#define BOOST_EXCEPTION_STATIC_TYPEID(T) ::boost::exception_detail::type_info_(BOOST_CORE_TYPEID(T)) + +#ifndef BOOST_NO_RTTI +#define BOOST_EXCEPTION_DYNAMIC_TYPEID(x) ::boost::exception_detail::type_info_(typeid(x)) +#endif + +#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) +#pragma warning(pop) +#endif +#endif diff --git a/refs/boost.asio/boost/exception/diagnostic_information.hpp b/refs/boost.asio/boost/exception/diagnostic_information.hpp new file mode 100644 index 0000000000000000000000000000000000000000..3872bb5e6cd93a2ebb5c135a7a9f5ffb7bf1391d --- /dev/null +++ b/refs/boost.asio/boost/exception/diagnostic_information.hpp @@ -0,0 +1,201 @@ +//Copyright (c) 2006-2010 Emil Dotchevski and Reverge Studios, Inc. + +//Distributed under the Boost Software License, Version 1.0. (See accompanying +//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef UUID_0552D49838DD11DD90146B8956D89593 +#define UUID_0552D49838DD11DD90146B8956D89593 +#if (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) +#pragma GCC system_header +#endif +#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) +#pragma warning(push,1) +#endif + +#include +#include +#include +#include +#ifndef BOOST_NO_RTTI +#include +#endif +#include +#include +#include + +#ifndef BOOST_NO_EXCEPTIONS +#include +namespace +boost + { + namespace + exception_detail + { + std::string diagnostic_information_impl( boost::exception const *, std::exception const *, bool, bool ); + } + + inline + std::string + current_exception_diagnostic_information( bool verbose=true) + { + boost::exception const * be=current_exception_cast(); + std::exception const * se=current_exception_cast(); + if( be || se ) + return exception_detail::diagnostic_information_impl(be,se,true,verbose); + else + return "No diagnostic information available."; + } + } +#endif + +namespace +boost + { + namespace + exception_detail + { + inline + exception const * + get_boost_exception( exception const * e ) + { + return e; + } + + inline + exception const * + get_boost_exception( ... ) + { + return 0; + } + + inline + std::exception const * + get_std_exception( std::exception const * e ) + { + return e; + } + + inline + std::exception const * + get_std_exception( ... ) + { + return 0; + } + + inline + char const * + get_diagnostic_information( exception const & x, char const * header ) + { +#ifndef BOOST_NO_EXCEPTIONS + try + { +#endif + error_info_container * c=x.data_.get(); + if( !c ) + x.data_.adopt(c=new exception_detail::error_info_container_impl); + char const * di=c->diagnostic_information(header); + BOOST_ASSERT(di!=0); + return di; +#ifndef BOOST_NO_EXCEPTIONS + } + catch(...) + { + return 0; + } +#endif + } + + inline + std::string + diagnostic_information_impl( boost::exception const * be, std::exception const * se, bool with_what, bool verbose ) + { + if( !be && !se ) + return "Unknown exception."; +#ifndef BOOST_NO_RTTI + if( !be ) + be=dynamic_cast(se); + if( !se ) + se=dynamic_cast(be); +#endif + char const * wh=0; + if( with_what && se ) + { + wh=se->what(); + if( be && exception_detail::get_diagnostic_information(*be,0)==wh ) + return wh; + } + std::ostringstream tmp; + if( be && verbose ) + { + char const * const * f=get_error_info(*be); + int const * l=get_error_info(*be); + char const * const * fn=get_error_info(*be); + if( !f && !l && !fn ) + tmp << "Throw location unknown (consider using BOOST_THROW_EXCEPTION)\n"; + else + { + if( f ) + { + tmp << *f; + if( int const * l=get_error_info(*be) ) + tmp << '(' << *l << "): "; + } + tmp << "Throw in function "; + if( char const * const * fn=get_error_info(*be) ) + tmp << *fn; + else + tmp << "(unknown)"; + tmp << '\n'; + } + } +#ifndef BOOST_NO_RTTI + if ( verbose ) + tmp << std::string("Dynamic exception type: ") << + core::demangle((be?(BOOST_EXCEPTION_DYNAMIC_TYPEID(*be)):(BOOST_EXCEPTION_DYNAMIC_TYPEID(*se))).type_->name()) << '\n'; +#endif + if( with_what && se && verbose ) + tmp << "std::exception::what: " << wh << '\n'; + if( be ) + if( char const * s=exception_detail::get_diagnostic_information(*be,tmp.str().c_str()) ) + if( *s ) + return std::string(s); + return tmp.str(); + } + } + + template + std::string + diagnostic_information( T const & e, bool verbose=true ) + { + return exception_detail::diagnostic_information_impl(exception_detail::get_boost_exception(&e),exception_detail::get_std_exception(&e),true,verbose); + } + + inline + char const * + diagnostic_information_what( exception const & e, bool verbose=true ) throw() + { + char const * w=0; +#ifndef BOOST_NO_EXCEPTIONS + try + { +#endif + (void) exception_detail::diagnostic_information_impl(&e,0,false,verbose); + if( char const * di=exception_detail::get_diagnostic_information(e,0) ) + return di; + else + return "Failed to produce boost::diagnostic_information_what()"; +#ifndef BOOST_NO_EXCEPTIONS + } + catch( + ... ) + { + } +#endif + return w; + } + } + +#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) +#pragma warning(pop) +#endif +#endif diff --git a/refs/boost.asio/boost/exception/errinfo_api_function.hpp b/refs/boost.asio/boost/exception/errinfo_api_function.hpp new file mode 100644 index 0000000000000000000000000000000000000000..7b6a9fee7670790c4893c4854497790e6dc64315 --- /dev/null +++ b/refs/boost.asio/boost/exception/errinfo_api_function.hpp @@ -0,0 +1,22 @@ +//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc. + +//Distributed under the Boost Software License, Version 1.0. (See accompanying +//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef UUID_DDFBB4546C1211DEA4659E9055D89593 +#define UUID_DDFBB4546C1211DEA4659E9055D89593 + +#include "boost/exception/error_info.hpp" + +namespace +boost + { + //Usage hint: + //if( api_function(....)!=0 ) + // BOOST_THROW_EXCEPTION( + // failure() << + // errinfo_api_function("api_function") ); + typedef error_info errinfo_api_function; + } + +#endif diff --git a/refs/boost.asio/boost/exception/errinfo_at_line.hpp b/refs/boost.asio/boost/exception/errinfo_at_line.hpp new file mode 100644 index 0000000000000000000000000000000000000000..cc422ce53b2c0b1e24ca1c17ecb1a4b9668954b4 --- /dev/null +++ b/refs/boost.asio/boost/exception/errinfo_at_line.hpp @@ -0,0 +1,18 @@ +//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc. + +//Distributed under the Boost Software License, Version 1.0. (See accompanying +//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef UUID_E7255CE26C1211DE85800C9155D89593 +#define UUID_E7255CE26C1211DE85800C9155D89593 + +namespace +boost + { + template class error_info; + + //Use with parsing errors exceptions, for example in a XML file parser. + typedef error_info errinfo_at_line; + } + +#endif diff --git a/refs/boost.asio/boost/exception/errinfo_errno.hpp b/refs/boost.asio/boost/exception/errinfo_errno.hpp new file mode 100644 index 0000000000000000000000000000000000000000..75a3dc94959d22f35ad1e756d6e11a094157f918 --- /dev/null +++ b/refs/boost.asio/boost/exception/errinfo_errno.hpp @@ -0,0 +1,44 @@ +//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc. + +//Distributed under the Boost Software License, Version 1.0. (See accompanying +//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef UUID_F0EE17BE6C1211DE87FF459155D89593 +#define UUID_F0EE17BE6C1211DE87FF459155D89593 +#if (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) +#pragma GCC system_header +#endif +#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) +#pragma warning(push,1) +#endif + +#include "boost/exception/info.hpp" +#include +#include + +namespace +boost + { + typedef error_info errinfo_errno; + + //Usage hint: + //if( c_function(....)!=0 ) + // BOOST_THROW_EXCEPTION( + // failure() << + // errinfo_errno(errno) << + // errinfo_api_function("c_function") ); + inline + std::string + to_string( errinfo_errno const & e ) + { + std::ostringstream tmp; + int v=e.value(); + tmp << v << ", \"" << strerror(v) << "\""; + return tmp.str(); + } + } + +#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) +#pragma warning(pop) +#endif +#endif diff --git a/refs/boost.asio/boost/exception/errinfo_file_handle.hpp b/refs/boost.asio/boost/exception/errinfo_file_handle.hpp new file mode 100644 index 0000000000000000000000000000000000000000..5b9673d70ea46c8b530b2fd1f686cd85967eb571 --- /dev/null +++ b/refs/boost.asio/boost/exception/errinfo_file_handle.hpp @@ -0,0 +1,20 @@ +//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc. + +//Distributed under the Boost Software License, Version 1.0. (See accompanying +//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef UUID_F79E6EE26C1211DEB26E929155D89593 +#define UUID_F79E6EE26C1211DEB26E929155D89593 + +#include + +namespace +boost + { + template class weak_ptr; + template class error_info; + + typedef error_info > errinfo_file_handle; + } + +#endif diff --git a/refs/boost.asio/boost/exception/errinfo_file_name.hpp b/refs/boost.asio/boost/exception/errinfo_file_name.hpp new file mode 100644 index 0000000000000000000000000000000000000000..c6f1c9e1045c0d04308b77f7a00b97282c215a70 --- /dev/null +++ b/refs/boost.asio/boost/exception/errinfo_file_name.hpp @@ -0,0 +1,26 @@ +//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc. + +//Distributed under the Boost Software License, Version 1.0. (See accompanying +//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef UUID_FEE5120A6C1211DE94E8BC9155D89593 +#define UUID_FEE5120A6C1211DE94E8BC9155D89593 + +#include + +namespace +boost + { + template class error_info; + + //Usage hint: + //FILE * f=fopen(name,mode); + //if( !f ) + // BOOST_THROW_EXCEPTION( + // file_open_error() << + // errinfo_file_name(name) << + // errinfo_file_open_mode(mode) ); + typedef error_info errinfo_file_name; + } + +#endif diff --git a/refs/boost.asio/boost/exception/errinfo_file_open_mode.hpp b/refs/boost.asio/boost/exception/errinfo_file_open_mode.hpp new file mode 100644 index 0000000000000000000000000000000000000000..c1bbaa15937d3c4ae7044b447f7265b66525b1c6 --- /dev/null +++ b/refs/boost.asio/boost/exception/errinfo_file_open_mode.hpp @@ -0,0 +1,26 @@ +//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc. + +//Distributed under the Boost Software License, Version 1.0. (See accompanying +//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef UUID_056F1F266C1311DE8E74299255D89593 +#define UUID_056F1F266C1311DE8E74299255D89593 + +#include + +namespace +boost + { + template class error_info; + + //Usage hint: + //FILE * f=fopen(name,mode); + //if( !f ) + // BOOST_THROW_EXCEPTION( + // file_open_error() << + // errinfo_file_name(name) << + // errinfo_file_open_mode(mode) ); + typedef error_info errinfo_file_open_mode; + } + +#endif diff --git a/refs/boost.asio/boost/exception/errinfo_nested_exception.hpp b/refs/boost.asio/boost/exception/errinfo_nested_exception.hpp new file mode 100644 index 0000000000000000000000000000000000000000..62bb5504f6ff7778ef8792ef712890126c52c4ba --- /dev/null +++ b/refs/boost.asio/boost/exception/errinfo_nested_exception.hpp @@ -0,0 +1,18 @@ +//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc. + +//Distributed under the Boost Software License, Version 1.0. (See accompanying +//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef UUID_45CC9A82B77511DEB330FC4956D89593 +#define UUID_45CC9A82B77511DEB330FC4956D89593 + +namespace +boost + { + namespace exception_detail { class clone_base; } + template class error_info; + class exception_ptr; + typedef error_info errinfo_nested_exception; + } + +#endif diff --git a/refs/boost.asio/boost/exception/errinfo_type_info_name.hpp b/refs/boost.asio/boost/exception/errinfo_type_info_name.hpp new file mode 100644 index 0000000000000000000000000000000000000000..dbd9abff09fcbfbc1fd95454dedf92cf022ae5d5 --- /dev/null +++ b/refs/boost.asio/boost/exception/errinfo_type_info_name.hpp @@ -0,0 +1,23 @@ +//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc. + +//Distributed under the Boost Software License, Version 1.0. (See accompanying +//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef UUID_0E11109E6C1311DEB7EA649255D89593 +#define UUID_0E11109E6C1311DEB7EA649255D89593 + +#include + +namespace +boost + { + template class error_info; + + //Usage hint: + //BOOST_THROW_EXCEPTION( + // bad_type() << + // errinfo_type_info_name(typeid(x).name()) ); + typedef error_info errinfo_type_info_name; + } + +#endif diff --git a/refs/boost.asio/boost/exception/error_info.hpp b/refs/boost.asio/boost/exception/error_info.hpp new file mode 100644 index 0000000000000000000000000000000000000000..14258bfe66219102399da8955dfa970c0c300cf4 --- /dev/null +++ b/refs/boost.asio/boost/exception/error_info.hpp @@ -0,0 +1,9 @@ +//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc. + +//Distributed under the Boost Software License, Version 1.0. (See accompanying +//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef UUID_EE7ECCA0433B11E1923E37064924019B +#define UUID_EE7ECCA0433B11E1923E37064924019B +namespace boost { template class error_info; } +#endif diff --git a/refs/boost.asio/boost/exception/get_error_info.hpp b/refs/boost.asio/boost/exception/get_error_info.hpp new file mode 100644 index 0000000000000000000000000000000000000000..f11418fa4d4d3014e082d6de46dabb632c38daaf --- /dev/null +++ b/refs/boost.asio/boost/exception/get_error_info.hpp @@ -0,0 +1,130 @@ +//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc. + +//Distributed under the Boost Software License, Version 1.0. (See accompanying +//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef UUID_1A590226753311DD9E4CCF6156D89593 +#define UUID_1A590226753311DD9E4CCF6156D89593 +#if (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) +#pragma GCC system_header +#endif +#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) +#pragma warning(push,1) +#endif + +#include +#include +#include +#include + +namespace +boost + { + namespace + exception_detail + { + template + struct + get_info + { + static + typename ErrorInfo::value_type * + get( exception const & x ) + { + if( exception_detail::error_info_container * c=x.data_.get() ) + if( shared_ptr eib = c->get(BOOST_EXCEPTION_STATIC_TYPEID(ErrorInfo)) ) + { +#ifndef BOOST_NO_RTTI + BOOST_ASSERT( 0!=dynamic_cast(eib.get()) ); +#endif + ErrorInfo * w = static_cast(eib.get()); + return &w->value(); + } + return 0; + } + }; + + template <> + struct + get_info + { + static + char const * * + get( exception const & x ) + { + return x.throw_function_ ? &x.throw_function_ : 0; + } + }; + + template <> + struct + get_info + { + static + char const * * + get( exception const & x ) + { + return x.throw_file_ ? &x.throw_file_ : 0; + } + }; + + template <> + struct + get_info + { + static + int * + get( exception const & x ) + { + return x.throw_line_!=-1 ? &x.throw_line_ : 0; + } + }; + + template + struct + get_error_info_return_type + { + typedef R * type; + }; + + template + struct + get_error_info_return_type + { + typedef R const * type; + }; + } + +#ifdef BOOST_NO_RTTI + template + inline + typename ErrorInfo::value_type const * + get_error_info( boost::exception const & x ) + { + return exception_detail::get_info::get(x); + } + template + inline + typename ErrorInfo::value_type * + get_error_info( boost::exception & x ) + { + return exception_detail::get_info::get(x); + } +#else + template + inline + typename exception_detail::get_error_info_return_type::type + get_error_info( E & some_exception ) + { + if( exception const * x = dynamic_cast(&some_exception) ) + return exception_detail::get_info::get(*x); + else + return 0; + } +#endif + } + +#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) +#pragma warning(pop) +#endif +#endif diff --git a/refs/boost.asio/boost/exception/info.hpp b/refs/boost.asio/boost/exception/info.hpp new file mode 100644 index 0000000000000000000000000000000000000000..80c18a13e449a8eac5ff23f3755038032c0e22f9 --- /dev/null +++ b/refs/boost.asio/boost/exception/info.hpp @@ -0,0 +1,198 @@ +//Copyright (c) 2006-2010 Emil Dotchevski and Reverge Studios, Inc. + +//Distributed under the Boost Software License, Version 1.0. (See accompanying +//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef UUID_8D22C4CA9CC811DCAA9133D256D89593 +#define UUID_8D22C4CA9CC811DCAA9133D256D89593 +#if (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) +#pragma GCC system_header +#endif +#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) +#pragma warning(push,1) +#endif + +#include +#include +#include +#include +#include +#include + +namespace +boost + { + template + inline + std::string + error_info_name( error_info const & x ) + { + return tag_type_name(); + } + + template + inline + std::string + to_string( error_info const & x ) + { + return '[' + error_info_name(x) + "] = " + to_string_stub(x.value()) + '\n'; + } + + template + inline + error_info:: + error_info( value_type const & value ): + value_(value) + { + } + + template + inline + error_info:: + ~error_info() throw() + { + } + + template + inline + std::string + error_info:: + name_value_string() const + { + return to_string_stub(*this); + } + + namespace + exception_detail + { + class + error_info_container_impl: + public error_info_container + { + public: + + error_info_container_impl(): + count_(0) + { + } + + ~error_info_container_impl() throw() + { + } + + void + set( shared_ptr const & x, type_info_ const & typeid_ ) + { + BOOST_ASSERT(x); + info_[typeid_] = x; + diagnostic_info_str_.clear(); + } + + shared_ptr + get( type_info_ const & ti ) const + { + error_info_map::const_iterator i=info_.find(ti); + if( info_.end()!=i ) + { + shared_ptr const & p = i->second; +#ifndef BOOST_NO_RTTI + BOOST_ASSERT( *BOOST_EXCEPTION_DYNAMIC_TYPEID(*p).type_==*ti.type_ ); +#endif + return p; + } + return shared_ptr(); + } + + char const * + diagnostic_information( char const * header ) const + { + if( header ) + { + std::ostringstream tmp; + tmp << header; + for( error_info_map::const_iterator i=info_.begin(),end=info_.end(); i!=end; ++i ) + { + error_info_base const & x = *i->second; + tmp << x.name_value_string(); + } + tmp.str().swap(diagnostic_info_str_); + } + return diagnostic_info_str_.c_str(); + } + + private: + + friend class boost::exception; + + typedef std::map< type_info_, shared_ptr > error_info_map; + error_info_map info_; + mutable std::string diagnostic_info_str_; + mutable int count_; + + error_info_container_impl( error_info_container_impl const & ); + error_info_container_impl & operator=( error_info_container const & ); + + void + add_ref() const + { + ++count_; + } + + bool + release() const + { + if( --count_ ) + return false; + else + { + delete this; + return true; + } + } + + refcount_ptr + clone() const + { + refcount_ptr p; + error_info_container_impl * c=new error_info_container_impl; + p.adopt(c); + c->info_ = info_; + return p; + } + }; + + template + inline + E const & + set_info( E const & x, error_info const & v ) + { + typedef error_info error_info_tag_t; + shared_ptr p( new error_info_tag_t(v) ); + exception_detail::error_info_container * c=x.data_.get(); + if( !c ) + x.data_.adopt(c=new exception_detail::error_info_container_impl); + c->set(p,BOOST_EXCEPTION_STATIC_TYPEID(error_info_tag_t)); + return x; + } + + template + struct + derives_boost_exception + { + enum e { value = (sizeof(dispatch_boost_exception((T*)0))==sizeof(large_size)) }; + }; + } + + template + inline + typename enable_if,E const &>::type + operator<<( E const & x, error_info const & v ) + { + return exception_detail::set_info(x,v); + } + } + +#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) +#pragma warning(pop) +#endif +#endif diff --git a/refs/boost.asio/boost/exception/info_tuple.hpp b/refs/boost.asio/boost/exception/info_tuple.hpp new file mode 100644 index 0000000000000000000000000000000000000000..b99bd6fb0620bef23e889a09ba5dd7aa3603c052 --- /dev/null +++ b/refs/boost.asio/boost/exception/info_tuple.hpp @@ -0,0 +1,100 @@ +//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc. + +//Distributed under the Boost Software License, Version 1.0. (See accompanying +//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef UUID_63EE924290FB11DC87BB856555D89593 +#define UUID_63EE924290FB11DC87BB856555D89593 +#if (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) +#pragma GCC system_header +#endif +#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) +#pragma warning(push,1) +#endif + +#include +#include + +namespace +boost + { + template < + class E > + inline + E const & + operator<<( + E const & x, + tuple< > const & v ) + { + return x; + } + + template < + class E, + class Tag1,class T1 > + inline + E const & + operator<<( + E const & x, + tuple< + error_info > const & v ) + { + return x << v.template get<0>(); + } + + template < + class E, + class Tag1,class T1, + class Tag2,class T2 > + inline + E const & + operator<<( + E const & x, + tuple< + error_info, + error_info > const & v ) + { + return x << v.template get<0>() << v.template get<1>(); + } + + template < + class E, + class Tag1,class T1, + class Tag2,class T2, + class Tag3,class T3 > + inline + E const & + operator<<( + E const & x, + tuple< + error_info, + error_info, + error_info > const & v ) + { + return x << v.template get<0>() << v.template get<1>() << v.template get<2>(); + } + + template < + class E, + class Tag1,class T1, + class Tag2,class T2, + class Tag3,class T3, + class Tag4,class T4 > + inline + E const & + operator<<( + E const & x, + tuple< + error_info, + error_info, + error_info, + error_info > const & v ) + { + return x << v.template get<0>() << v.template get<1>() << v.template get<2>() << v.template get<3>(); + } + } + +#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) +#pragma warning(pop) +#endif +#endif diff --git a/refs/boost.asio/boost/exception/to_string.hpp b/refs/boost.asio/boost/exception/to_string.hpp new file mode 100644 index 0000000000000000000000000000000000000000..72e0a59127e75151a851958217289eb7085da386 --- /dev/null +++ b/refs/boost.asio/boost/exception/to_string.hpp @@ -0,0 +1,88 @@ +//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc. + +//Distributed under the Boost Software License, Version 1.0. (See accompanying +//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef UUID_7E48761AD92811DC9011477D56D89593 +#define UUID_7E48761AD92811DC9011477D56D89593 +#if (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) +#pragma GCC system_header +#endif +#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) +#pragma warning(push,1) +#endif + +#include +#include +#include + +namespace +boost + { + template + std::string to_string( std::pair const & ); + std::string to_string( std::exception const & ); + + namespace + to_string_detail + { + template + typename disable_if,char>::type to_string( T const & ); + using boost::to_string; + + template + struct has_to_string_impl; + + template + struct + has_to_string_impl + { + enum e { value=1 }; + }; + + template + struct + has_to_string_impl + { + static T const & f(); + enum e { value=1!=sizeof(to_string(f())) }; + }; + } + + template + inline + typename enable_if,std::string>::type + to_string( T const & x ) + { + std::ostringstream out; + out << x; + return out.str(); + } + + template + struct + has_to_string + { + enum e { value=to_string_detail::has_to_string_impl::value>::value }; + }; + + template + inline + std::string + to_string( std::pair const & x ) + { + return std::string("(") + to_string(x.first) + ',' + to_string(x.second) + ')'; + } + + inline + std::string + to_string( std::exception const & x ) + { + return x.what(); + } + } + +#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) +#pragma warning(pop) +#endif +#endif diff --git a/refs/boost.asio/boost/exception/to_string_stub.hpp b/refs/boost.asio/boost/exception/to_string_stub.hpp new file mode 100644 index 0000000000000000000000000000000000000000..ad897adefdc70fc6a002ac2629d2824523e40d59 --- /dev/null +++ b/refs/boost.asio/boost/exception/to_string_stub.hpp @@ -0,0 +1,117 @@ +//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc. + +//Distributed under the Boost Software License, Version 1.0. (See accompanying +//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef UUID_E788439ED9F011DCB181F25B55D89593 +#define UUID_E788439ED9F011DCB181F25B55D89593 +#if (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) +#pragma GCC system_header +#endif +#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) +#pragma warning(push,1) +#endif + +#include +#include +#include + +namespace +boost + { + namespace + exception_detail + { + template + struct + to_string_dispatcher + { + template + static + std::string + convert( T const & x, Stub ) + { + return to_string(x); + } + }; + + template <> + struct + to_string_dispatcher + { + template + static + std::string + convert( T const & x, Stub s ) + { + return s(x); + } + + template + static + std::string + convert( T const & x, std::string s ) + { + return s; + } + + template + static + std::string + convert( T const & x, char const * s ) + { + BOOST_ASSERT(s!=0); + return s; + } + }; + + namespace + to_string_dispatch + { + template + inline + std::string + dispatch( T const & x, Stub s ) + { + return to_string_dispatcher::value>::convert(x,s); + } + } + + template + inline + std::string + string_stub_dump( T const & x ) + { + return "[ " + exception_detail::object_hex_dump(x) + " ]"; + } + } + + template + inline + std::string + to_string_stub( T const & x ) + { + return exception_detail::to_string_dispatch::dispatch(x,&exception_detail::string_stub_dump); + } + + template + inline + std::string + to_string_stub( T const & x, Stub s ) + { + return exception_detail::to_string_dispatch::dispatch(x,s); + } + + template + inline + std::string + to_string_stub( std::pair const & x, Stub s ) + { + return std::string("(") + to_string_stub(x.first,s) + ',' + to_string_stub(x.second,s) + ')'; + } + } + +#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) +#pragma warning(pop) +#endif +#endif diff --git a/refs/boost.asio/boost/exception_ptr.hpp b/refs/boost.asio/boost/exception_ptr.hpp new file mode 100644 index 0000000000000000000000000000000000000000..9900b586041a156d02e0e53f1cc4a3145baef91d --- /dev/null +++ b/refs/boost.asio/boost/exception_ptr.hpp @@ -0,0 +1,11 @@ +//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc. + +//Distributed under the Boost Software License, Version 1.0. (See accompanying +//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef UUID_FA5836A2CADA11DC8CD47C8555D89593 +#define UUID_FA5836A2CADA11DC8CD47C8555D89593 + +#include + +#endif diff --git a/refs/boost.asio/boost/tuple/detail/tuple_basic.hpp b/refs/boost.asio/boost/tuple/detail/tuple_basic.hpp new file mode 100644 index 0000000000000000000000000000000000000000..1060c7a2c9591050452b96bfd4200700429151fc --- /dev/null +++ b/refs/boost.asio/boost/tuple/detail/tuple_basic.hpp @@ -0,0 +1,989 @@ +// tuple_basic.hpp ----------------------------------------------------- + +// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// For more information, see http://www.boost.org + +// Outside help: +// This and that, Gary Powell. +// Fixed return types for get_head/get_tail +// ( and other bugs ) per suggestion of Jens Maurer +// simplified element type accessors + bug fix (Jeremy Siek) +// Several changes/additions according to suggestions by Douglas Gregor, +// William Kempf, Vesa Karvonen, John Max Skaller, Ed Brey, Beman Dawes, +// David Abrahams. + +// Revision history: +// 2002 05 01 Hugo Duncan: Fix for Borland after Jaakko's previous changes +// 2002 04 18 Jaakko: tuple element types can be void or plain function +// types, as long as no object is created. +// Tuple objects can no hold even noncopyable types +// such as arrays. +// 2001 10 22 John Maddock +// Fixes for Borland C++ +// 2001 08 30 David Abrahams +// Added default constructor for cons<>. +// ----------------------------------------------------------------- + +#ifndef BOOST_TUPLE_BASIC_HPP +#define BOOST_TUPLE_BASIC_HPP + + +#include // needed for the assignment from pair to tuple + +#include "boost/type_traits/cv_traits.hpp" +#include "boost/type_traits/function_traits.hpp" +#include "boost/utility/swap.hpp" + +#include "boost/detail/workaround.hpp" // needed for BOOST_WORKAROUND + +#if BOOST_GCC >= 40700 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-local-typedefs" +#endif + +namespace boost { +namespace tuples { + +// -- null_type -------------------------------------------------------- +struct null_type {}; + +// a helper function to provide a const null_type type temporary +namespace detail { + inline const null_type cnull() { return null_type(); } + + +// -- if construct ------------------------------------------------ +// Proposed by Krzysztof Czarnecki and Ulrich Eisenecker + +template struct IF { typedef Then RET; }; + +template struct IF { + typedef Else RET; +}; + +} // end detail + +// - cons forward declaration ----------------------------------------------- +template struct cons; + + +// - tuple forward declaration ----------------------------------------------- +template < + class T0 = null_type, class T1 = null_type, class T2 = null_type, + class T3 = null_type, class T4 = null_type, class T5 = null_type, + class T6 = null_type, class T7 = null_type, class T8 = null_type, + class T9 = null_type> +class tuple; + +// tuple_length forward declaration +template struct length; + + + +namespace detail { + +// -- generate error template, referencing to non-existing members of this +// template is used to produce compilation errors intentionally +template +class generate_error; + +template +struct drop_front { + template + struct apply { + typedef BOOST_DEDUCED_TYPENAME drop_front::BOOST_NESTED_TEMPLATE + apply next; + typedef BOOST_DEDUCED_TYPENAME next::type::tail_type type; + static const type& call(const Tuple& tup) { + return next::call(tup).tail; + } + }; +}; + +template<> +struct drop_front<0> { + template + struct apply { + typedef Tuple type; + static const type& call(const Tuple& tup) { + return tup; + } + }; +}; + +} // end of namespace detail + + +// -cons type accessors ---------------------------------------- +// typename tuples::element::type gets the type of the +// Nth element ot T, first element is at index 0 +// ------------------------------------------------------- + +#ifndef BOOST_NO_CV_SPECIALIZATIONS + +template +struct element +{ + typedef BOOST_DEDUCED_TYPENAME detail::drop_front::BOOST_NESTED_TEMPLATE + apply::type::head_type type; +}; + +template +struct element +{ +private: + typedef BOOST_DEDUCED_TYPENAME detail::drop_front::BOOST_NESTED_TEMPLATE + apply::type::head_type unqualified_type; +public: +#if BOOST_WORKAROUND(__BORLANDC__,<0x600) + typedef const unqualified_type type; +#else + typedef BOOST_DEDUCED_TYPENAME boost::add_const::type type; +#endif +}; +#else // def BOOST_NO_CV_SPECIALIZATIONS + +namespace detail { + +template +struct element_impl +{ + typedef BOOST_DEDUCED_TYPENAME detail::drop_front::BOOST_NESTED_TEMPLATE + apply::type::head_type type; +}; + +template +struct element_impl +{ + typedef BOOST_DEDUCED_TYPENAME detail::drop_front::BOOST_NESTED_TEMPLATE + apply::type::head_type unqualified_type; + typedef const unqualified_type type; +}; + +} // end of namespace detail + + +template +struct element: + public detail::element_impl::value> +{ +}; + +#endif + + +// -get function templates ----------------------------------------------- +// Usage: get(aTuple) + +// -- some traits classes for get functions + +// access traits lifted from detail namespace to be part of the interface, +// (Joel de Guzman's suggestion). Rationale: get functions are part of the +// interface, so should the way to express their return types be. + +template struct access_traits { + typedef const T& const_type; + typedef T& non_const_type; + + typedef const typename boost::remove_cv::type& parameter_type; + +// used as the tuple constructors parameter types +// Rationale: non-reference tuple element types can be cv-qualified. +// It should be possible to initialize such types with temporaries, +// and when binding temporaries to references, the reference must +// be non-volatile and const. 8.5.3. (5) +}; + +template struct access_traits { + + typedef T& const_type; + typedef T& non_const_type; + + typedef T& parameter_type; +}; + +// get function for non-const cons-lists, returns a reference to the element + +template +inline typename access_traits< + typename element >::type + >::non_const_type +get(cons& c) { + typedef BOOST_DEDUCED_TYPENAME detail::drop_front::BOOST_NESTED_TEMPLATE + apply > impl; + typedef BOOST_DEDUCED_TYPENAME impl::type cons_element; + return const_cast(impl::call(c)).head; +} + +// get function for const cons-lists, returns a const reference to +// the element. If the element is a reference, returns the reference +// as such (that is, can return a non-const reference) +template +inline typename access_traits< + typename element >::type + >::const_type +get(const cons& c) { + typedef BOOST_DEDUCED_TYPENAME detail::drop_front::BOOST_NESTED_TEMPLATE + apply > impl; + return impl::call(c).head; +} + +// -- the cons template -------------------------------------------------- +namespace detail { + +// These helper templates wrap void types and plain function types. +// The reationale is to allow one to write tuple types with those types +// as elements, even though it is not possible to instantiate such object. +// E.g: typedef tuple some_type; // ok +// but: some_type x; // fails + +template class non_storeable_type { + non_storeable_type(); +}; + +template struct wrap_non_storeable_type { + typedef typename IF< + ::boost::is_function::value, non_storeable_type, T + >::RET type; +}; +template <> struct wrap_non_storeable_type { + typedef non_storeable_type type; +}; + +} // detail + +template +struct cons { + + typedef HT head_type; + typedef TT tail_type; + + typedef typename + detail::wrap_non_storeable_type::type stored_head_type; + + stored_head_type head; + tail_type tail; + + typename access_traits::non_const_type + get_head() { return head; } + + typename access_traits::non_const_type + get_tail() { return tail; } + + typename access_traits::const_type + get_head() const { return head; } + + typename access_traits::const_type + get_tail() const { return tail; } + + cons() : head(), tail() {} + // cons() : head(detail::default_arg::f()), tail() {} + + // the argument for head is not strictly needed, but it prevents + // array type elements. This is good, since array type elements + // cannot be supported properly in any case (no assignment, + // copy works only if the tails are exactly the same type, ...) + + cons(typename access_traits::parameter_type h, + const tail_type& t) + : head (h), tail(t) {} + + template + cons( T1& t1, T2& t2, T3& t3, T4& t4, T5& t5, + T6& t6, T7& t7, T8& t8, T9& t9, T10& t10 ) + : head (t1), + tail (t2, t3, t4, t5, t6, t7, t8, t9, t10, detail::cnull()) + {} + + template + cons( const null_type& /*t1*/, T2& t2, T3& t3, T4& t4, T5& t5, + T6& t6, T7& t7, T8& t8, T9& t9, T10& t10 ) + : head (), + tail (t2, t3, t4, t5, t6, t7, t8, t9, t10, detail::cnull()) + {} + + + template + cons( const cons& u ) : head(u.head), tail(u.tail) {} + + template + cons& operator=( const cons& u ) { + head=u.head; tail=u.tail; return *this; + } + + // must define assignment operator explicitly, implicit version is + // illformed if HT is a reference (12.8. (12)) + cons& operator=(const cons& u) { + head = u.head; tail = u.tail; return *this; + } + + template + cons& operator=( const std::pair& u ) { + BOOST_STATIC_ASSERT(length::value == 2); // check length = 2 + head = u.first; tail.head = u.second; return *this; + } + + // get member functions (non-const and const) + template + typename access_traits< + typename element >::type + >::non_const_type + get() { + return boost::tuples::get(*this); // delegate to non-member get + } + + template + typename access_traits< + typename element >::type + >::const_type + get() const { + return boost::tuples::get(*this); // delegate to non-member get + } +}; + +template +struct cons { + + typedef HT head_type; + typedef null_type tail_type; + typedef cons self_type; + + typedef typename + detail::wrap_non_storeable_type::type stored_head_type; + stored_head_type head; + + typename access_traits::non_const_type + get_head() { return head; } + + null_type get_tail() { return null_type(); } + + typename access_traits::const_type + get_head() const { return head; } + + const null_type get_tail() const { return null_type(); } + + // cons() : head(detail::default_arg::f()) {} + cons() : head() {} + + cons(typename access_traits::parameter_type h, + const null_type& = null_type()) + : head (h) {} + + template + cons(T1& t1, const null_type&, const null_type&, const null_type&, + const null_type&, const null_type&, const null_type&, + const null_type&, const null_type&, const null_type&) + : head (t1) {} + + cons(const null_type&, + const null_type&, const null_type&, const null_type&, + const null_type&, const null_type&, const null_type&, + const null_type&, const null_type&, const null_type&) + : head () {} + + template + cons( const cons& u ) : head(u.head) {} + + template + cons& operator=(const cons& u ) + { head = u.head; return *this; } + + // must define assignment operator explicitely, implicit version + // is illformed if HT is a reference + cons& operator=(const cons& u) { head = u.head; return *this; } + + template + typename access_traits< + typename element::type + >::non_const_type + get() { + return boost::tuples::get(*this); + } + + template + typename access_traits< + typename element::type + >::const_type + get() const { + return boost::tuples::get(*this); + } + +}; + +// templates for finding out the length of the tuple ------------------- + +template +struct length { + BOOST_STATIC_CONSTANT(int, value = 1 + length::value); +}; + +template<> +struct length > { + BOOST_STATIC_CONSTANT(int, value = 0); +}; + +template<> +struct length const> { + BOOST_STATIC_CONSTANT(int, value = 0); +}; + +template<> +struct length { + BOOST_STATIC_CONSTANT(int, value = 0); +}; + +template<> +struct length { + BOOST_STATIC_CONSTANT(int, value = 0); +}; + +namespace detail { + +// Tuple to cons mapper -------------------------------------------------- +template +struct map_tuple_to_cons +{ + typedef cons::type + > type; +}; + +// The empty tuple is a null_type +template <> +struct map_tuple_to_cons +{ + typedef null_type type; +}; + +} // end detail + +// ------------------------------------------------------------------- +// -- tuple ------------------------------------------------------ +template + +class tuple : + public detail::map_tuple_to_cons::type +{ +public: + typedef typename + detail::map_tuple_to_cons::type inherited; + typedef typename inherited::head_type head_type; + typedef typename inherited::tail_type tail_type; + + +// access_traits::parameter_type takes non-reference types as const T& + tuple() {} + + tuple(typename access_traits::parameter_type t0) + : inherited(t0, detail::cnull(), detail::cnull(), detail::cnull(), + detail::cnull(), detail::cnull(), detail::cnull(), + detail::cnull(), detail::cnull(), detail::cnull()) {} + + tuple(typename access_traits::parameter_type t0, + typename access_traits::parameter_type t1) + : inherited(t0, t1, detail::cnull(), detail::cnull(), + detail::cnull(), detail::cnull(), detail::cnull(), + detail::cnull(), detail::cnull(), detail::cnull()) {} + + tuple(typename access_traits::parameter_type t0, + typename access_traits::parameter_type t1, + typename access_traits::parameter_type t2) + : inherited(t0, t1, t2, detail::cnull(), detail::cnull(), + detail::cnull(), detail::cnull(), detail::cnull(), + detail::cnull(), detail::cnull()) {} + + tuple(typename access_traits::parameter_type t0, + typename access_traits::parameter_type t1, + typename access_traits::parameter_type t2, + typename access_traits::parameter_type t3) + : inherited(t0, t1, t2, t3, detail::cnull(), detail::cnull(), + detail::cnull(), detail::cnull(), detail::cnull(), + detail::cnull()) {} + + tuple(typename access_traits::parameter_type t0, + typename access_traits::parameter_type t1, + typename access_traits::parameter_type t2, + typename access_traits::parameter_type t3, + typename access_traits::parameter_type t4) + : inherited(t0, t1, t2, t3, t4, detail::cnull(), detail::cnull(), + detail::cnull(), detail::cnull(), detail::cnull()) {} + + tuple(typename access_traits::parameter_type t0, + typename access_traits::parameter_type t1, + typename access_traits::parameter_type t2, + typename access_traits::parameter_type t3, + typename access_traits::parameter_type t4, + typename access_traits::parameter_type t5) + : inherited(t0, t1, t2, t3, t4, t5, detail::cnull(), detail::cnull(), + detail::cnull(), detail::cnull()) {} + + tuple(typename access_traits::parameter_type t0, + typename access_traits::parameter_type t1, + typename access_traits::parameter_type t2, + typename access_traits::parameter_type t3, + typename access_traits::parameter_type t4, + typename access_traits::parameter_type t5, + typename access_traits::parameter_type t6) + : inherited(t0, t1, t2, t3, t4, t5, t6, detail::cnull(), + detail::cnull(), detail::cnull()) {} + + tuple(typename access_traits::parameter_type t0, + typename access_traits::parameter_type t1, + typename access_traits::parameter_type t2, + typename access_traits::parameter_type t3, + typename access_traits::parameter_type t4, + typename access_traits::parameter_type t5, + typename access_traits::parameter_type t6, + typename access_traits::parameter_type t7) + : inherited(t0, t1, t2, t3, t4, t5, t6, t7, detail::cnull(), + detail::cnull()) {} + + tuple(typename access_traits::parameter_type t0, + typename access_traits::parameter_type t1, + typename access_traits::parameter_type t2, + typename access_traits::parameter_type t3, + typename access_traits::parameter_type t4, + typename access_traits::parameter_type t5, + typename access_traits::parameter_type t6, + typename access_traits::parameter_type t7, + typename access_traits::parameter_type t8) + : inherited(t0, t1, t2, t3, t4, t5, t6, t7, t8, detail::cnull()) {} + + tuple(typename access_traits::parameter_type t0, + typename access_traits::parameter_type t1, + typename access_traits::parameter_type t2, + typename access_traits::parameter_type t3, + typename access_traits::parameter_type t4, + typename access_traits::parameter_type t5, + typename access_traits::parameter_type t6, + typename access_traits::parameter_type t7, + typename access_traits::parameter_type t8, + typename access_traits::parameter_type t9) + : inherited(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9) {} + + + template + tuple(const cons& p) : inherited(p) {} + + template + tuple& operator=(const cons& k) { + inherited::operator=(k); + return *this; + } + + template + tuple& operator=(const std::pair& k) { + BOOST_STATIC_ASSERT(length::value == 2);// check_length = 2 + this->head = k.first; + this->tail.head = k.second; + return *this; + } + +}; + +// The empty tuple +template <> +class tuple : + public null_type +{ +public: + typedef null_type inherited; +}; + + +// Swallows any assignment (by Doug Gregor) +namespace detail { + +struct swallow_assign; +typedef void (detail::swallow_assign::*ignore_t)(); +struct swallow_assign { + swallow_assign(ignore_t(*)(ignore_t)) {} + template + swallow_assign const& operator=(const T&) const { + return *this; + } +}; + + +} // namespace detail + +// "ignore" allows tuple positions to be ignored when using "tie". +inline detail::ignore_t ignore(detail::ignore_t) { return 0; } + +// --------------------------------------------------------------------------- +// The call_traits for make_tuple +// Honours the reference_wrapper class. + +// Must be instantiated with plain or const plain types (not with references) + +// from template foo(const T& t) : make_tuple_traits::type +// from template foo(T& t) : make_tuple_traits::type + +// Conversions: +// T -> T, +// references -> compile_time_error +// reference_wrapper -> T& +// const reference_wrapper -> T& +// array -> const ref array + + +template +struct make_tuple_traits { + typedef T type; + + // commented away, see below (JJ) + // typedef typename IF< + // boost::is_function::value, + // T&, + // T>::RET type; + +}; + +// The is_function test was there originally for plain function types, +// which can't be stored as such (we must either store them as references or +// pointers). Such a type could be formed if make_tuple was called with a +// reference to a function. +// But this would mean that a const qualified function type was formed in +// the make_tuple function and hence make_tuple can't take a function +// reference as a parameter, and thus T can't be a function type. +// So is_function test was removed. +// (14.8.3. says that type deduction fails if a cv-qualified function type +// is created. (It only applies for the case of explicitly specifying template +// args, though?)) (JJ) + +template +struct make_tuple_traits { + typedef typename + detail::generate_error:: + do_not_use_with_reference_type error; +}; + +// Arrays can't be stored as plain types; convert them to references. +// All arrays are converted to const. This is because make_tuple takes its +// parameters as const T& and thus the knowledge of the potential +// non-constness of actual argument is lost. +template struct make_tuple_traits { + typedef const T (&type)[n]; +}; + +template +struct make_tuple_traits { + typedef const T (&type)[n]; +}; + +template struct make_tuple_traits { + typedef const volatile T (&type)[n]; +}; + +template +struct make_tuple_traits { + typedef const volatile T (&type)[n]; +}; + +template +struct make_tuple_traits >{ + typedef T& type; +}; + +template +struct make_tuple_traits >{ + typedef T& type; +}; + +template<> +struct make_tuple_traits { + typedef detail::swallow_assign type; +}; + + + +namespace detail { + +// a helper traits to make the make_tuple functions shorter (Vesa Karvonen's +// suggestion) +template < + class T0 = null_type, class T1 = null_type, class T2 = null_type, + class T3 = null_type, class T4 = null_type, class T5 = null_type, + class T6 = null_type, class T7 = null_type, class T8 = null_type, + class T9 = null_type +> +struct make_tuple_mapper { + typedef + tuple::type, + typename make_tuple_traits::type, + typename make_tuple_traits::type, + typename make_tuple_traits::type, + typename make_tuple_traits::type, + typename make_tuple_traits::type, + typename make_tuple_traits::type, + typename make_tuple_traits::type, + typename make_tuple_traits::type, + typename make_tuple_traits::type> type; +}; + +} // end detail + +// -make_tuple function templates ----------------------------------- +inline tuple<> make_tuple() { + return tuple<>(); +} + +template +inline typename detail::make_tuple_mapper::type +make_tuple(const T0& t0) { + typedef typename detail::make_tuple_mapper::type t; + return t(t0); +} + +template +inline typename detail::make_tuple_mapper::type +make_tuple(const T0& t0, const T1& t1) { + typedef typename detail::make_tuple_mapper::type t; + return t(t0, t1); +} + +template +inline typename detail::make_tuple_mapper::type +make_tuple(const T0& t0, const T1& t1, const T2& t2) { + typedef typename detail::make_tuple_mapper::type t; + return t(t0, t1, t2); +} + +template +inline typename detail::make_tuple_mapper::type +make_tuple(const T0& t0, const T1& t1, const T2& t2, const T3& t3) { + typedef typename detail::make_tuple_mapper::type t; + return t(t0, t1, t2, t3); +} + +template +inline typename detail::make_tuple_mapper::type +make_tuple(const T0& t0, const T1& t1, const T2& t2, const T3& t3, + const T4& t4) { + typedef typename detail::make_tuple_mapper::type t; + return t(t0, t1, t2, t3, t4); +} + +template +inline typename detail::make_tuple_mapper::type +make_tuple(const T0& t0, const T1& t1, const T2& t2, const T3& t3, + const T4& t4, const T5& t5) { + typedef typename detail::make_tuple_mapper::type t; + return t(t0, t1, t2, t3, t4, t5); +} + +template +inline typename detail::make_tuple_mapper::type +make_tuple(const T0& t0, const T1& t1, const T2& t2, const T3& t3, + const T4& t4, const T5& t5, const T6& t6) { + typedef typename detail::make_tuple_mapper + ::type t; + return t(t0, t1, t2, t3, t4, t5, t6); +} + +template +inline typename detail::make_tuple_mapper::type +make_tuple(const T0& t0, const T1& t1, const T2& t2, const T3& t3, + const T4& t4, const T5& t5, const T6& t6, const T7& t7) { + typedef typename detail::make_tuple_mapper + ::type t; + return t(t0, t1, t2, t3, t4, t5, t6, t7); +} + +template +inline typename detail::make_tuple_mapper + ::type +make_tuple(const T0& t0, const T1& t1, const T2& t2, const T3& t3, + const T4& t4, const T5& t5, const T6& t6, const T7& t7, + const T8& t8) { + typedef typename detail::make_tuple_mapper + ::type t; + return t(t0, t1, t2, t3, t4, t5, t6, t7, t8); +} + +template +inline typename detail::make_tuple_mapper + ::type +make_tuple(const T0& t0, const T1& t1, const T2& t2, const T3& t3, + const T4& t4, const T5& t5, const T6& t6, const T7& t7, + const T8& t8, const T9& t9) { + typedef typename detail::make_tuple_mapper + ::type t; + return t(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9); +} + +namespace detail { + +template +struct tie_traits { + typedef T& type; +}; + +template<> +struct tie_traits { + typedef swallow_assign type; +}; + +template<> +struct tie_traits { + typedef null_type type; +}; + +template < + class T0 = void, class T1 = void, class T2 = void, + class T3 = void, class T4 = void, class T5 = void, + class T6 = void, class T7 = void, class T8 = void, + class T9 = void +> +struct tie_mapper { + typedef + tuple::type, + typename tie_traits::type, + typename tie_traits::type, + typename tie_traits::type, + typename tie_traits::type, + typename tie_traits::type, + typename tie_traits::type, + typename tie_traits::type, + typename tie_traits::type, + typename tie_traits::type> type; +}; + +} + +// Tie function templates ------------------------------------------------- +template +inline typename detail::tie_mapper::type +tie(T0& t0) { + typedef typename detail::tie_mapper::type t; + return t(t0); +} + +template +inline typename detail::tie_mapper::type +tie(T0& t0, T1& t1) { + typedef typename detail::tie_mapper::type t; + return t(t0, t1); +} + +template +inline typename detail::tie_mapper::type +tie(T0& t0, T1& t1, T2& t2) { + typedef typename detail::tie_mapper::type t; + return t(t0, t1, t2); +} + +template +inline typename detail::tie_mapper::type +tie(T0& t0, T1& t1, T2& t2, T3& t3) { + typedef typename detail::tie_mapper::type t; + return t(t0, t1, t2, t3); +} + +template +inline typename detail::tie_mapper::type +tie(T0& t0, T1& t1, T2& t2, T3& t3, + T4& t4) { + typedef typename detail::tie_mapper::type t; + return t(t0, t1, t2, t3, t4); +} + +template +inline typename detail::tie_mapper::type +tie(T0& t0, T1& t1, T2& t2, T3& t3, + T4& t4, T5& t5) { + typedef typename detail::tie_mapper::type t; + return t(t0, t1, t2, t3, t4, t5); +} + +template +inline typename detail::tie_mapper::type +tie(T0& t0, T1& t1, T2& t2, T3& t3, + T4& t4, T5& t5, T6& t6) { + typedef typename detail::tie_mapper + ::type t; + return t(t0, t1, t2, t3, t4, t5, t6); +} + +template +inline typename detail::tie_mapper::type +tie(T0& t0, T1& t1, T2& t2, T3& t3, + T4& t4, T5& t5, T6& t6, T7& t7) { + typedef typename detail::tie_mapper + ::type t; + return t(t0, t1, t2, t3, t4, t5, t6, t7); +} + +template +inline typename detail::tie_mapper + ::type +tie(T0& t0, T1& t1, T2& t2, T3& t3, + T4& t4, T5& t5, T6& t6, T7& t7, + T8& t8) { + typedef typename detail::tie_mapper + ::type t; + return t(t0, t1, t2, t3, t4, t5, t6, t7, t8); +} + +template +inline typename detail::tie_mapper + ::type +tie(T0& t0, T1& t1, T2& t2, T3& t3, + T4& t4, T5& t5, T6& t6, T7& t7, + T8& t8, T9& t9) { + typedef typename detail::tie_mapper + ::type t; + return t(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9); +} + +template +void swap(tuple& lhs, + tuple& rhs); +inline void swap(null_type&, null_type&) {} +template +inline void swap(cons& lhs, cons& rhs) { + ::boost::swap(lhs.head, rhs.head); +} +template +inline void swap(cons& lhs, cons& rhs) { + ::boost::swap(lhs.head, rhs.head); + ::boost::tuples::swap(lhs.tail, rhs.tail); +} +template +inline void swap(tuple& lhs, + tuple& rhs) { + typedef tuple tuple_type; + typedef typename tuple_type::inherited base; + ::boost::tuples::swap(static_cast(lhs), static_cast(rhs)); +} + +} // end of namespace tuples +} // end of namespace boost + + +#if BOOST_GCC >= 40700 +#pragma GCC diagnostic pop +#endif + + +#endif // BOOST_TUPLE_BASIC_HPP + + diff --git a/refs/boost.asio/boost/tuple/tuple.hpp b/refs/boost.asio/boost/tuple/tuple.hpp new file mode 100644 index 0000000000000000000000000000000000000000..6e9f9125b95aa8d65ef6d096b7d552a4ea126201 --- /dev/null +++ b/refs/boost.asio/boost/tuple/tuple.hpp @@ -0,0 +1,67 @@ +// tuple.hpp - Boost Tuple Library -------------------------------------- + +// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// For more information, see http://www.boost.org + +// ----------------------------------------------------------------- + +#ifndef BOOST_TUPLE_HPP +#define BOOST_TUPLE_HPP + +#if defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730 +// Work around a compiler bug. +// boost::python::tuple has to be seen by the compiler before the +// boost::tuple class template. +namespace boost { namespace python { class tuple; }} +#endif + +#include "boost/config.hpp" +#include "boost/static_assert.hpp" + +// other compilers +#include "boost/ref.hpp" +#include "boost/tuple/detail/tuple_basic.hpp" + + +namespace boost { + +using tuples::tuple; +using tuples::make_tuple; +using tuples::tie; +#if !defined(BOOST_NO_USING_TEMPLATE) +using tuples::get; +#else +// +// The "using tuples::get" statement causes the +// Borland compiler to ICE, use forwarding +// functions instead: +// +template +inline typename tuples::access_traits< + typename tuples::element >::type + >::non_const_type +get(tuples::cons& c) { + return tuples::get(c); +} +// get function for const cons-lists, returns a const reference to +// the element. If the element is a reference, returns the reference +// as such (that is, can return a non-const reference) +template +inline typename tuples::access_traits< + typename tuples::element >::type + >::const_type +get(const tuples::cons& c) { + return tuples::get(c); +} + +#endif // BOOST_NO_USING_TEMPLATE + +} // end namespace boost + + +#endif // BOOST_TUPLE_HPP diff --git a/refs/boost.asio/boost/type_traits/add_cv.hpp b/refs/boost.asio/boost/type_traits/add_cv.hpp new file mode 100644 index 0000000000000000000000000000000000000000..5bda213065d251aaf12e5d99f7679aae63b3ad21 --- /dev/null +++ b/refs/boost.asio/boost/type_traits/add_cv.hpp @@ -0,0 +1,41 @@ + +// (C) Copyright Dave Abrahams, Steve Cleary, Beman Dawes, Howard +// Hinnant & John Maddock 2000. +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt). +// +// See http://www.boost.org/libs/type_traits for most recent version including documentation. + + +#ifndef BOOST_TT_ADD_CV_HPP_INCLUDED +#define BOOST_TT_ADD_CV_HPP_INCLUDED + +#include + +namespace boost { + +// * convert a type T to a const volatile type - add_cv +// this is not required since the result is always +// the same as "T const volatile", but it does suppress warnings +// from some compilers: + +#if defined(BOOST_MSVC) +// This bogus warning will appear when add_volatile is applied to a +// const volatile reference because we can't detect const volatile +// references with MSVC6. +# pragma warning(push) +# pragma warning(disable:4181) // warning C4181: qualifier applied to reference type ignored +#endif + +template struct add_cv{ typedef T const volatile type; }; + +#if defined(BOOST_MSVC) +# pragma warning(pop) +#endif + +template struct add_cv{ typedef T& type; }; + +} // namespace boost + +#endif // BOOST_TT_ADD_CV_HPP_INCLUDED diff --git a/refs/boost.asio/boost/type_traits/add_pointer.hpp b/refs/boost.asio/boost/type_traits/add_pointer.hpp new file mode 100644 index 0000000000000000000000000000000000000000..01922710f65e09c7b7530888181a25be2801aa15 --- /dev/null +++ b/refs/boost.asio/boost/type_traits/add_pointer.hpp @@ -0,0 +1,61 @@ + +// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000. +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt). +// +// See http://www.boost.org/libs/type_traits for most recent version including documentation. + +#ifndef BOOST_TT_ADD_POINTER_HPP_INCLUDED +#define BOOST_TT_ADD_POINTER_HPP_INCLUDED + +#include + +namespace boost { + +#if defined(__BORLANDC__) && (__BORLANDC__ < 0x5A0) +// +// For some reason this implementation stops Borlands compiler +// from dropping cv-qualifiers, it still fails with references +// to arrays for some reason though (shrug...) (JM 20021104) +// +template +struct add_pointer +{ + typedef T* type; +}; +template +struct add_pointer +{ + typedef T* type; +}; +template +struct add_pointer +{ + typedef T* type; +}; +template +struct add_pointer +{ + typedef T* type; +}; +template +struct add_pointer +{ + typedef T* type; +}; + +#else + +template +struct add_pointer +{ + typedef typename remove_reference::type no_ref_type; + typedef no_ref_type* type; +}; + +#endif + +} // namespace boost + +#endif // BOOST_TT_ADD_POINTER_HPP_INCLUDED diff --git a/refs/boost.asio/boost/type_traits/add_volatile.hpp b/refs/boost.asio/boost/type_traits/add_volatile.hpp new file mode 100644 index 0000000000000000000000000000000000000000..a15144b9e1c1bb4e30454432a8fe0c5f756a07f9 --- /dev/null +++ b/refs/boost.asio/boost/type_traits/add_volatile.hpp @@ -0,0 +1,40 @@ + +// (C) Copyright Dave Abrahams, Steve Cleary, Beman Dawes, Howard +// Hinnant & John Maddock 2000. +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt). +// +// See http://www.boost.org/libs/type_traits for most recent version including documentation. + +#ifndef BOOST_TT_ADD_VOLATILE_HPP_INCLUDED +#define BOOST_TT_ADD_VOLATILE_HPP_INCLUDED + +#include + +namespace boost { + +// * convert a type T to volatile type - add_volatile +// this is not required since the result is always +// the same as "T volatile", but it does suppress warnings +// from some compilers: + +#if defined(BOOST_MSVC) +// This bogus warning will appear when add_volatile is applied to a +// const volatile reference because we can't detect const volatile +// references with MSVC6. +# pragma warning(push) +# pragma warning(disable:4181) // warning C4181: qualifier applied to reference type ignored +#endif + +template struct add_volatile{ typedef T volatile type; }; + +#if defined(BOOST_MSVC) +# pragma warning(pop) +#endif + +template struct add_volatile{ typedef T& type; }; + +} // namespace boost + +#endif // BOOST_TT_ADD_VOLATILE_HPP_INCLUDED diff --git a/refs/boost.asio/boost/type_traits/cv_traits.hpp b/refs/boost.asio/boost/type_traits/cv_traits.hpp new file mode 100644 index 0000000000000000000000000000000000000000..63c78442e15baef87ef112618debee2aefd59770 --- /dev/null +++ b/refs/boost.asio/boost/type_traits/cv_traits.hpp @@ -0,0 +1,24 @@ +// (C) Copyright Dave Abrahams, Steve Cleary, Beman Dawes, Howard +// Hinnant & John Maddock 2000. +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt). +// +// See http://www.boost.org/libs/type_traits for most recent version including documentation. +// +// defines traits classes for cv-qualified types: +// is_const, is_volatile, remove_const, remove_volatile, remove_cv. + +#ifndef BOOST_TT_CV_TRAITS_HPP_INCLUDED +#define BOOST_TT_CV_TRAITS_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include +#include +#include + +#endif // BOOST_TT_CV_TRAITS_HPP_INCLUDED diff --git a/refs/boost.asio/boost/type_traits/detail/is_function_ptr_tester.hpp b/refs/boost.asio/boost/type_traits/detail/is_function_ptr_tester.hpp new file mode 100644 index 0000000000000000000000000000000000000000..3b61db08d3aa2c60045fa03e0d49190d25d11f5d --- /dev/null +++ b/refs/boost.asio/boost/type_traits/detail/is_function_ptr_tester.hpp @@ -0,0 +1,449 @@ + +// (C) Copyright Dave Abrahams, Steve Cleary, Beman Dawes, +// Aleksey Gurtovoy, Howard Hinnant & John Maddock 2000. +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt). +// +// See http://www.boost.org/libs/type_traits for most recent version including documentation. + +#if !defined(BOOST_PP_IS_ITERATING) + +///// header body + +#ifndef BOOST_TT_DETAIL_IS_FUNCTION_PTR_TESTER_HPP_INCLUDED +#define BOOST_TT_DETAIL_IS_FUNCTION_PTR_TESTER_HPP_INCLUDED + +#include + +#if defined(BOOST_TT_PREPROCESSING_MODE) +// +// Hide include dependencies from analysers since they're +// only require in maintenance mode: +// +#define PP1 +#define PP2 +#define PP3 +#include PP1 +#include PP2 +#include PP3 +#undef PP1 +#undef PP2 +#undef PP3 +#endif + +namespace boost { +namespace type_traits { + +// Note it is acceptable to use ellipsis here, since the argument will +// always be a pointer type of some sort (JM 2005/06/04): +no_type BOOST_TT_DECL is_function_ptr_tester(...); + +#if !defined(BOOST_TT_PREPROCESSING_MODE) +// pre-processed code, don't edit, try GNU cpp with +// cpp -I../../../ -DBOOST_TT_PREPROCESSING_MODE -x c++ -P filename + +template +yes_type is_function_ptr_tester(R (*)()); +template +yes_type is_function_ptr_tester(R (*)( ...)); +#ifdef BOOST_TT_TEST_MS_FUNC_SIGS +template +yes_type is_function_ptr_tester(R (__stdcall*)()); +#ifndef _MANAGED +template +yes_type is_function_ptr_tester(R (__fastcall*)()); +#endif +template +yes_type is_function_ptr_tester(R (__cdecl*)()); +#endif +template +yes_type is_function_ptr_tester(R (*)( T0)); +template +yes_type is_function_ptr_tester(R (*)( T0 ...)); +#ifdef BOOST_TT_TEST_MS_FUNC_SIGS +template +yes_type is_function_ptr_tester(R (__stdcall*)( T0)); +#ifndef _MANAGED +template +yes_type is_function_ptr_tester(R (__fastcall*)( T0)); +#endif +template +yes_type is_function_ptr_tester(R (__cdecl*)( T0)); +#endif +template +yes_type is_function_ptr_tester(R (*)( T0 , T1)); +template +yes_type is_function_ptr_tester(R (*)( T0 , T1 ...)); +#ifdef BOOST_TT_TEST_MS_FUNC_SIGS +template +yes_type is_function_ptr_tester(R (__stdcall*)( T0 , T1)); +#ifndef _MANAGED +template +yes_type is_function_ptr_tester(R (__fastcall*)( T0 , T1)); +#endif +template +yes_type is_function_ptr_tester(R (__cdecl*)( T0 , T1)); +#endif +template +yes_type is_function_ptr_tester(R (*)( T0 , T1 , T2)); +template +yes_type is_function_ptr_tester(R (*)( T0 , T1 , T2 ...)); +#ifdef BOOST_TT_TEST_MS_FUNC_SIGS +template +yes_type is_function_ptr_tester(R (__stdcall*)( T0 , T1 , T2)); +#ifndef _MANAGED +template +yes_type is_function_ptr_tester(R (__fastcall*)( T0 , T1 , T2)); +#endif +template +yes_type is_function_ptr_tester(R (__cdecl*)( T0 , T1 , T2)); +#endif +template +yes_type is_function_ptr_tester(R (*)( T0 , T1 , T2 , T3)); +template +yes_type is_function_ptr_tester(R (*)( T0 , T1 , T2 , T3 ...)); +#ifdef BOOST_TT_TEST_MS_FUNC_SIGS +template +yes_type is_function_ptr_tester(R (__stdcall*)( T0 , T1 , T2 , T3)); +#ifndef _MANAGED +template +yes_type is_function_ptr_tester(R (__fastcall*)( T0 , T1 , T2 , T3)); +#endif +template +yes_type is_function_ptr_tester(R (__cdecl*)( T0 , T1 , T2 , T3)); +#endif +template +yes_type is_function_ptr_tester(R (*)( T0 , T1 , T2 , T3 , T4)); +template +yes_type is_function_ptr_tester(R (*)( T0 , T1 , T2 , T3 , T4 ...)); +#ifdef BOOST_TT_TEST_MS_FUNC_SIGS +template +yes_type is_function_ptr_tester(R (__stdcall*)( T0 , T1 , T2 , T3 , T4)); +#ifndef _MANAGED +template +yes_type is_function_ptr_tester(R (__fastcall*)( T0 , T1 , T2 , T3 , T4)); +#endif +template +yes_type is_function_ptr_tester(R (__cdecl*)( T0 , T1 , T2 , T3 , T4)); +#endif +template +yes_type is_function_ptr_tester(R (*)( T0 , T1 , T2 , T3 , T4 , T5)); +template +yes_type is_function_ptr_tester(R (*)( T0 , T1 , T2 , T3 , T4 , T5 ...)); +#ifdef BOOST_TT_TEST_MS_FUNC_SIGS +template +yes_type is_function_ptr_tester(R (__stdcall*)( T0 , T1 , T2 , T3 , T4 , T5)); +#ifndef _MANAGED +template +yes_type is_function_ptr_tester(R (__fastcall*)( T0 , T1 , T2 , T3 , T4 , T5)); +#endif +template +yes_type is_function_ptr_tester(R (__cdecl*)( T0 , T1 , T2 , T3 , T4 , T5)); +#endif +template +yes_type is_function_ptr_tester(R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6)); +template +yes_type is_function_ptr_tester(R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 ...)); +#ifdef BOOST_TT_TEST_MS_FUNC_SIGS +template +yes_type is_function_ptr_tester(R (__stdcall*)( T0 , T1 , T2 , T3 , T4 , T5 , T6)); +#ifndef _MANAGED +template +yes_type is_function_ptr_tester(R (__fastcall*)( T0 , T1 , T2 , T3 , T4 , T5 , T6)); +#endif +template +yes_type is_function_ptr_tester(R (__cdecl*)( T0 , T1 , T2 , T3 , T4 , T5 , T6)); +#endif +template +yes_type is_function_ptr_tester(R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7)); +template +yes_type is_function_ptr_tester(R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 ...)); +#ifdef BOOST_TT_TEST_MS_FUNC_SIGS +template +yes_type is_function_ptr_tester(R (__stdcall*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7)); +#ifndef _MANAGED +template +yes_type is_function_ptr_tester(R (__fastcall*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7)); +#endif +template +yes_type is_function_ptr_tester(R (__cdecl*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7)); +#endif +template +yes_type is_function_ptr_tester(R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8)); +template +yes_type is_function_ptr_tester(R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 ...)); +#ifdef BOOST_TT_TEST_MS_FUNC_SIGS +template +yes_type is_function_ptr_tester(R (__stdcall*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8)); +#ifndef _MANAGED +template +yes_type is_function_ptr_tester(R (__fastcall*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8)); +#endif +template +yes_type is_function_ptr_tester(R (__cdecl*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8)); +#endif +template +yes_type is_function_ptr_tester(R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9)); +template +yes_type is_function_ptr_tester(R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 ...)); +#ifdef BOOST_TT_TEST_MS_FUNC_SIGS +template +yes_type is_function_ptr_tester(R (__stdcall*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9)); +#ifndef _MANAGED +template +yes_type is_function_ptr_tester(R (__fastcall*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9)); +#endif +template +yes_type is_function_ptr_tester(R (__cdecl*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9)); +#endif +template +yes_type is_function_ptr_tester(R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10)); +template +yes_type is_function_ptr_tester(R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 ...)); +#ifdef BOOST_TT_TEST_MS_FUNC_SIGS +template +yes_type is_function_ptr_tester(R (__stdcall*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10)); +#ifndef _MANAGED +template +yes_type is_function_ptr_tester(R (__fastcall*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10)); +#endif +template +yes_type is_function_ptr_tester(R (__cdecl*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10)); +#endif +template +yes_type is_function_ptr_tester(R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11)); +template +yes_type is_function_ptr_tester(R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 ...)); +#ifdef BOOST_TT_TEST_MS_FUNC_SIGS +template +yes_type is_function_ptr_tester(R (__stdcall*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11)); +#ifndef _MANAGED +template +yes_type is_function_ptr_tester(R (__fastcall*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11)); +#endif +template +yes_type is_function_ptr_tester(R (__cdecl*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11)); +#endif +template +yes_type is_function_ptr_tester(R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12)); +template +yes_type is_function_ptr_tester(R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 ...)); +#ifdef BOOST_TT_TEST_MS_FUNC_SIGS +template +yes_type is_function_ptr_tester(R (__stdcall*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12)); +#ifndef _MANAGED +template +yes_type is_function_ptr_tester(R (__fastcall*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12)); +#endif +template +yes_type is_function_ptr_tester(R (__cdecl*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12)); +#endif +template +yes_type is_function_ptr_tester(R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13)); +template +yes_type is_function_ptr_tester(R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 ...)); +#ifdef BOOST_TT_TEST_MS_FUNC_SIGS +template +yes_type is_function_ptr_tester(R (__stdcall*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13)); +#ifndef _MANAGED +template +yes_type is_function_ptr_tester(R (__fastcall*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13)); +#endif +template +yes_type is_function_ptr_tester(R (__cdecl*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13)); +#endif +template +yes_type is_function_ptr_tester(R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14)); +template +yes_type is_function_ptr_tester(R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 ...)); +#ifdef BOOST_TT_TEST_MS_FUNC_SIGS +template +yes_type is_function_ptr_tester(R (__stdcall*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14)); +#ifndef _MANAGED +template +yes_type is_function_ptr_tester(R (__fastcall*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14)); +#endif +template +yes_type is_function_ptr_tester(R (__cdecl*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14)); +#endif +template +yes_type is_function_ptr_tester(R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15)); +template +yes_type is_function_ptr_tester(R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 ...)); +#ifdef BOOST_TT_TEST_MS_FUNC_SIGS +template +yes_type is_function_ptr_tester(R (__stdcall*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15)); +#ifndef _MANAGED +template +yes_type is_function_ptr_tester(R (__fastcall*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15)); +#endif +template +yes_type is_function_ptr_tester(R (__cdecl*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15)); +#endif +template +yes_type is_function_ptr_tester(R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16)); +template +yes_type is_function_ptr_tester(R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 ...)); +#ifdef BOOST_TT_TEST_MS_FUNC_SIGS +template +yes_type is_function_ptr_tester(R (__stdcall*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16)); +#ifndef _MANAGED +template +yes_type is_function_ptr_tester(R (__fastcall*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16)); +#endif +template +yes_type is_function_ptr_tester(R (__cdecl*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16)); +#endif +template +yes_type is_function_ptr_tester(R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17)); +template +yes_type is_function_ptr_tester(R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 ...)); +#ifdef BOOST_TT_TEST_MS_FUNC_SIGS +template +yes_type is_function_ptr_tester(R (__stdcall*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17)); +#ifndef _MANAGED +template +yes_type is_function_ptr_tester(R (__fastcall*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17)); +#endif +template +yes_type is_function_ptr_tester(R (__cdecl*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17)); +#endif +template +yes_type is_function_ptr_tester(R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18)); +template +yes_type is_function_ptr_tester(R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 ...)); +#ifdef BOOST_TT_TEST_MS_FUNC_SIGS +template +yes_type is_function_ptr_tester(R (__stdcall*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18)); +#ifndef _MANAGED +template +yes_type is_function_ptr_tester(R (__fastcall*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18)); +#endif +template +yes_type is_function_ptr_tester(R (__cdecl*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18)); +#endif +template +yes_type is_function_ptr_tester(R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19)); +template +yes_type is_function_ptr_tester(R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 ...)); +#ifdef BOOST_TT_TEST_MS_FUNC_SIGS +template +yes_type is_function_ptr_tester(R (__stdcall*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19)); +#ifndef _MANAGED +template +yes_type is_function_ptr_tester(R (__fastcall*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19)); +#endif +template +yes_type is_function_ptr_tester(R (__cdecl*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19)); +#endif +template +yes_type is_function_ptr_tester(R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20)); +template +yes_type is_function_ptr_tester(R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 ...)); +#ifdef BOOST_TT_TEST_MS_FUNC_SIGS +template +yes_type is_function_ptr_tester(R (__stdcall*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20)); +#ifndef _MANAGED +template +yes_type is_function_ptr_tester(R (__fastcall*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20)); +#endif +template +yes_type is_function_ptr_tester(R (__cdecl*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20)); +#endif +template +yes_type is_function_ptr_tester(R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21)); +template +yes_type is_function_ptr_tester(R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 ...)); +#ifdef BOOST_TT_TEST_MS_FUNC_SIGS +template +yes_type is_function_ptr_tester(R (__stdcall*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21)); +#ifndef _MANAGED +template +yes_type is_function_ptr_tester(R (__fastcall*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21)); +#endif +template +yes_type is_function_ptr_tester(R (__cdecl*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21)); +#endif +template +yes_type is_function_ptr_tester(R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22)); +template +yes_type is_function_ptr_tester(R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 ...)); +#ifdef BOOST_TT_TEST_MS_FUNC_SIGS +template +yes_type is_function_ptr_tester(R (__stdcall*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22)); +#ifndef _MANAGED +template +yes_type is_function_ptr_tester(R (__fastcall*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22)); +#endif +template +yes_type is_function_ptr_tester(R (__cdecl*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22)); +#endif +template +yes_type is_function_ptr_tester(R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23)); +template +yes_type is_function_ptr_tester(R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 ...)); +#ifdef BOOST_TT_TEST_MS_FUNC_SIGS +template +yes_type is_function_ptr_tester(R (__stdcall*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23)); +#ifndef _MANAGED +template +yes_type is_function_ptr_tester(R (__fastcall*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23)); +#endif +template +yes_type is_function_ptr_tester(R (__cdecl*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23)); +#endif +template +yes_type is_function_ptr_tester(R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24)); +template +yes_type is_function_ptr_tester(R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 ...)); +#ifdef BOOST_TT_TEST_MS_FUNC_SIGS +template +yes_type is_function_ptr_tester(R (__stdcall*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24)); +#ifndef _MANAGED +template +yes_type is_function_ptr_tester(R (__fastcall*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24)); +#endif +template +yes_type is_function_ptr_tester(R (__cdecl*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24)); +#endif +#else + +#define BOOST_PP_ITERATION_PARAMS_1 \ + (3, (0, 25, "boost/type_traits/detail/is_function_ptr_tester.hpp")) +#include BOOST_PP_ITERATE() + +#endif // BOOST_TT_PREPROCESSING_MODE + +} // namespace type_traits +} // namespace boost + +#endif // BOOST_TT_DETAIL_IS_FUNCTION_PTR_TESTER_HPP_INCLUDED + +///// iteration + +#else +#define BOOST_PP_COUNTER BOOST_PP_FRAME_ITERATION(1) +#undef __stdcall +#undef __fastcall +#undef __cdecl + +template +yes_type is_function_ptr_tester(R (*)(BOOST_PP_ENUM_PARAMS(BOOST_PP_COUNTER,T))); +@#ifndef BOOST_TT_NO_ELLIPSIS_IN_FUNC_TESTING +template +yes_type is_function_ptr_tester(R (*)(BOOST_PP_ENUM_PARAMS(BOOST_PP_COUNTER,T) ...)); +@#endif +@#ifdef BOOST_TT_TEST_MS_FUNC_SIGS +template +yes_type is_function_ptr_tester(R (__stdcall*)(BOOST_PP_ENUM_PARAMS(BOOST_PP_COUNTER,T))); +@#ifndef _MANAGED +template +yes_type is_function_ptr_tester(R (__fastcall*)(BOOST_PP_ENUM_PARAMS(BOOST_PP_COUNTER,T))); +@#endif +template +yes_type is_function_ptr_tester(R (__cdecl*)(BOOST_PP_ENUM_PARAMS(BOOST_PP_COUNTER,T))); +@#endif + +#undef BOOST_PP_COUNTER +#endif // BOOST_PP_IS_ITERATING diff --git a/refs/boost.asio/boost/type_traits/detail/yes_no_type.hpp b/refs/boost.asio/boost/type_traits/detail/yes_no_type.hpp new file mode 100644 index 0000000000000000000000000000000000000000..f62087fe66bf5e6ea4193287c1369c0e2ecef290 --- /dev/null +++ b/refs/boost.asio/boost/type_traits/detail/yes_no_type.hpp @@ -0,0 +1,26 @@ + +// (C) Copyright John Maddock and Steve Cleary 2000. +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt). +// +// See http://www.boost.org/libs/type_traits for most recent version including documentation. +// +// macros and helpers for working with integral-constant-expressions. + +#ifndef BOOST_TT_DETAIL_YES_NO_TYPE_HPP_INCLUDED +#define BOOST_TT_DETAIL_YES_NO_TYPE_HPP_INCLUDED + +namespace boost { +namespace type_traits { + +typedef char yes_type; +struct no_type +{ + char padding[8]; +}; + +} // namespace type_traits +} // namespace boost + +#endif // BOOST_TT_DETAIL_YES_NO_TYPE_HPP_INCLUDED diff --git a/refs/boost.asio/boost/type_traits/function_traits.hpp b/refs/boost.asio/boost/type_traits/function_traits.hpp new file mode 100644 index 0000000000000000000000000000000000000000..0e3b265bfb2fbcab3b2d90ab2ab3da657646f0bf --- /dev/null +++ b/refs/boost.asio/boost/type_traits/function_traits.hpp @@ -0,0 +1,174 @@ + +// Copyright 2000 John Maddock (john@johnmaddock.co.uk) +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt). +// +// See http://www.boost.org/libs/type_traits for most recent version including documentation. + +#ifndef BOOST_TT_FUNCTION_TRAITS_HPP_INCLUDED +#define BOOST_TT_FUNCTION_TRAITS_HPP_INCLUDED + +#include +#include +#include + +namespace boost { + +namespace detail { + +template struct function_traits_helper; + +template +struct function_traits_helper +{ + BOOST_STATIC_CONSTANT(unsigned, arity = 0); + typedef R result_type; +}; + +template +struct function_traits_helper +{ + BOOST_STATIC_CONSTANT(unsigned, arity = 1); + typedef R result_type; + typedef T1 arg1_type; + typedef T1 argument_type; +}; + +template +struct function_traits_helper +{ + BOOST_STATIC_CONSTANT(unsigned, arity = 2); + typedef R result_type; + typedef T1 arg1_type; + typedef T2 arg2_type; + typedef T1 first_argument_type; + typedef T2 second_argument_type; +}; + +template +struct function_traits_helper +{ + BOOST_STATIC_CONSTANT(unsigned, arity = 3); + typedef R result_type; + typedef T1 arg1_type; + typedef T2 arg2_type; + typedef T3 arg3_type; +}; + +template +struct function_traits_helper +{ + BOOST_STATIC_CONSTANT(unsigned, arity = 4); + typedef R result_type; + typedef T1 arg1_type; + typedef T2 arg2_type; + typedef T3 arg3_type; + typedef T4 arg4_type; +}; + +template +struct function_traits_helper +{ + BOOST_STATIC_CONSTANT(unsigned, arity = 5); + typedef R result_type; + typedef T1 arg1_type; + typedef T2 arg2_type; + typedef T3 arg3_type; + typedef T4 arg4_type; + typedef T5 arg5_type; +}; + +template +struct function_traits_helper +{ + BOOST_STATIC_CONSTANT(unsigned, arity = 6); + typedef R result_type; + typedef T1 arg1_type; + typedef T2 arg2_type; + typedef T3 arg3_type; + typedef T4 arg4_type; + typedef T5 arg5_type; + typedef T6 arg6_type; +}; + +template +struct function_traits_helper +{ + BOOST_STATIC_CONSTANT(unsigned, arity = 7); + typedef R result_type; + typedef T1 arg1_type; + typedef T2 arg2_type; + typedef T3 arg3_type; + typedef T4 arg4_type; + typedef T5 arg5_type; + typedef T6 arg6_type; + typedef T7 arg7_type; +}; + +template +struct function_traits_helper +{ + BOOST_STATIC_CONSTANT(unsigned, arity = 8); + typedef R result_type; + typedef T1 arg1_type; + typedef T2 arg2_type; + typedef T3 arg3_type; + typedef T4 arg4_type; + typedef T5 arg5_type; + typedef T6 arg6_type; + typedef T7 arg7_type; + typedef T8 arg8_type; +}; + +template +struct function_traits_helper +{ + BOOST_STATIC_CONSTANT(unsigned, arity = 9); + typedef R result_type; + typedef T1 arg1_type; + typedef T2 arg2_type; + typedef T3 arg3_type; + typedef T4 arg4_type; + typedef T5 arg5_type; + typedef T6 arg6_type; + typedef T7 arg7_type; + typedef T8 arg8_type; + typedef T9 arg9_type; +}; + +template +struct function_traits_helper +{ + BOOST_STATIC_CONSTANT(unsigned, arity = 10); + typedef R result_type; + typedef T1 arg1_type; + typedef T2 arg2_type; + typedef T3 arg3_type; + typedef T4 arg4_type; + typedef T5 arg5_type; + typedef T6 arg6_type; + typedef T7 arg7_type; + typedef T8 arg8_type; + typedef T9 arg9_type; + typedef T10 arg10_type; +}; + +} // end namespace detail + +template +struct function_traits : + public boost::detail::function_traits_helper::type> +{ +}; + +} + +#endif // BOOST_TT_FUNCTION_TRAITS_HPP_INCLUDED diff --git a/refs/boost.asio/boost/type_traits/is_volatile.hpp b/refs/boost.asio/boost/type_traits/is_volatile.hpp new file mode 100644 index 0000000000000000000000000000000000000000..8433df606a43a1f9a8da1f1fce625bd4068859a4 --- /dev/null +++ b/refs/boost.asio/boost/type_traits/is_volatile.hpp @@ -0,0 +1,45 @@ + +// (C) Copyright Dave Abrahams, Steve Cleary, Beman Dawes, +// Howard Hinnant and John Maddock 2000. +// (C) Copyright Mat Marcus, Jesse Jones and Adobe Systems Inc 2001 + +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt). +// +// See http://www.boost.org/libs/type_traits for most recent version including documentation. + +// Fixed is_pointer, is_reference, is_const, is_volatile, is_same, +// is_member_pointer based on the Simulated Partial Specialization work +// of Mat Marcus and Jesse Jones. See http://opensource.adobe.com or +// http://groups.yahoo.com/group/boost/message/5441 +// Some workarounds in here use ideas suggested from "Generic: +// Mappings between Types and Values" +// by Andrei Alexandrescu (see http://www.cuj.com/experts/1810/alexandr.html). + + +#ifndef BOOST_TT_IS_VOLATILE_HPP_INCLUDED +#define BOOST_TT_IS_VOLATILE_HPP_INCLUDED + +#include + +namespace boost { + +#if defined( __CODEGEARC__ ) + + template + struct is_volatile : public integral_constant {}; + +#else + + template + struct is_volatile : public false_type {}; + template struct is_volatile : public true_type{}; + template struct is_volatile : public true_type{}; + template struct is_volatile : public true_type{}; + +#endif + +} // namespace boost + +#endif // BOOST_TT_IS_VOLATILE_HPP_INCLUDED diff --git a/refs/boost.asio/boost/type_traits/remove_const.hpp b/refs/boost.asio/boost/type_traits/remove_const.hpp new file mode 100644 index 0000000000000000000000000000000000000000..5d4f994f859e213f61efba171d9e0a844d5e2a01 --- /dev/null +++ b/refs/boost.asio/boost/type_traits/remove_const.hpp @@ -0,0 +1,33 @@ + +// (C) Copyright Dave Abrahams, Steve Cleary, Beman Dawes, Howard +// Hinnant & John Maddock 2000. +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt). +// +// See http://www.boost.org/libs/type_traits for most recent version including documentation. + + +#ifndef BOOST_TT_REMOVE_CONST_HPP_INCLUDED +#define BOOST_TT_REMOVE_CONST_HPP_INCLUDED + +#include +#include +#include + +namespace boost { + + // convert a type T to a non-cv-qualified type - remove_const + template struct remove_const{ typedef T type; }; + template struct remove_const{ typedef T type; }; + +#if !defined(BOOST_NO_ARRAY_TYPE_SPECIALIZATIONS) + template struct remove_const{ typedef T type[N]; }; +#if !BOOST_WORKAROUND(__BORLANDC__, < 0x600) && !defined(__IBMCPP__) && !BOOST_WORKAROUND(__DMC__, BOOST_TESTED_AT(0x840)) + template struct remove_const{ typedef T type[]; }; +#endif +#endif + +} // namespace boost + +#endif // BOOST_TT_REMOVE_CONST_HPP_INCLUDED diff --git a/refs/boost.asio/boost/type_traits/remove_volatile.hpp b/refs/boost.asio/boost/type_traits/remove_volatile.hpp new file mode 100644 index 0000000000000000000000000000000000000000..d5fce7e9fd55f897a76bdf3a2094d2bea001a99b --- /dev/null +++ b/refs/boost.asio/boost/type_traits/remove_volatile.hpp @@ -0,0 +1,34 @@ + +// (C) Copyright Dave Abrahams, Steve Cleary, Beman Dawes, Howard +// Hinnant & John Maddock 2000. +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt). +// +// See http://www.boost.org/libs/type_traits for most recent version including documentation. + + +#ifndef BOOST_TT_REMOVE_VOLATILE_HPP_INCLUDED +#define BOOST_TT_REMOVE_VOLATILE_HPP_INCLUDED + +#include +#include +#include + +namespace boost { + + // convert a type T to a non-cv-qualified type - remove_volatile + template struct remove_volatile{ typedef T type; }; + template struct remove_volatile{ typedef T type; }; + +#if !defined(BOOST_NO_ARRAY_TYPE_SPECIALIZATIONS) + template struct remove_volatile{ typedef T type[N]; }; +#if !BOOST_WORKAROUND(__BORLANDC__, < 0x600) && !defined(__IBMCPP__) && !BOOST_WORKAROUND(__DMC__, BOOST_TESTED_AT(0x840)) + template struct remove_volatile{ typedef T type[]; }; +#endif +#endif + + +} // namespace boost + +#endif // BOOST_TT_REMOVE_VOLATILE_HPP_INCLUDED diff --git a/refs/boost.asio/boost/utility/swap.hpp b/refs/boost.asio/boost/utility/swap.hpp new file mode 100644 index 0000000000000000000000000000000000000000..b0866d770e49939deb38efef004c7eef99996c4b --- /dev/null +++ b/refs/boost.asio/boost/utility/swap.hpp @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2014 Glen Fernandes + * + * Distributed under the Boost Software License, Version 1.0. (See + * accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + */ + +#ifndef BOOST_UTILITY_SWAP_HPP +#define BOOST_UTILITY_SWAP_HPP + +// The header file at this path is deprecated; +// use boost/core/swap.hpp instead. + +#include + +#endif diff --git a/refs/boost.asio/readme.txt b/refs/boost.asio/readme.txt index ec1c2b013ac80d050ee57203b12672c3538f3997..dea0927bbb474d7579f0e9875b18e492078664fc 100644 --- a/refs/boost.asio/readme.txt +++ b/refs/boost.asio/readme.txt @@ -15,3 +15,12 @@ firstly, add aditionnal includes path "Root Of boost.asio.1.0.161 Directory" to #3.Currently Win32, Android and Apple(OS X/iOS) compile succeed. #4.Please open c++11 flags(-std=c++11) for Android compile. + + +BOOST_ASIO_DISABLE_DEV_POLL: Explicitly disables /dev/poll support on Solaris, forcing the use of a select-based implementation. +BOOST_ASIO_DISABLE_EPOLL: Explicitly disables epoll support on Linux, forcing the use of a select-based implementation. +BOOST_ASIO_DISABLE_EVENTFD: Explicitly disables eventfd support on Linux, forcing the use of a pipe to interrupt blocked epoll/select system calls. +BOOST_ASIO_DISABLE_KQUEUE: Explicitly disables kqueue support on Mac OS X and BSD variants, forcing the use of a select-based implementation. +BOOST_ASIO_DISABLE_IOCP: Explicitly disables I/O completion ports support on Windows, forcing the use of a select-based implementation. + +More detail: http://think-async.com/Asio/boost_asio_1_10_6/doc/html/boost_asio/using.html diff --git a/src/aes.h b/src/aes.h new file mode 100644 index 0000000000000000000000000000000000000000..58cbe813e5000cf158c16f152096c6964c8409e6 --- /dev/null +++ b/src/aes.h @@ -0,0 +1,188 @@ +/* crypto/aes/aes.h -*- mode:C; c-file-style: "eay" -*- */ +/* ==================================================================== +* Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* +* 3. All advertising materials mentioning features or use of this +* software must display the following acknowledgment: +* "This product includes software developed by the OpenSSL Project +* for use in the OpenSSL Toolkit. (http://www.openssl.org/)" +* +* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to +* endorse or promote products derived from this software without +* prior written permission. For written permission, please contact +* openssl-core@openssl.org. +* +* 5. Products derived from this software may not be called "OpenSSL" +* nor may "OpenSSL" appear in their names without prior written +* permission of the OpenSSL Project. +* +* 6. Redistributions of any form whatsoever must retain the following +* acknowledgment: +* "This product includes software developed by the OpenSSL Project +* for use in the OpenSSL Toolkit (http://www.openssl.org/)" +* +* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY +* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR +* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +* OF THE POSSIBILITY OF SUCH DAMAGE. +* ==================================================================== +* +*/ + +#ifndef HEADER_AES_H +#define HEADER_AES_H + +//#include + +#ifdef OPENSSL_NO_AES +#error AES is disabled. +#endif + +#define _HAS_OSSL 1 +#define _OSSL_USE_DLL 0 + +#if _HAS_OSSL + +#ifdef _WIN32 + #if _USE_OSSL_DLL + #define _OSSL_DLL __declspec(dllimport) + #else + #define _OSSL_DLL + #endif +#else + #define _OSSL_DLL +#endif + +#define ossl_aes_options AES_options +#define ossl_aes_set_encrypt_key AES_set_encrypt_key +#define ossl_aes_set_decrypt_key AES_set_decrypt_key +#define ossl_aes_encrypt AES_encrypt +#define ossl_aes_decrypt AES_decrypt +#define ossl_aes_ecb_encrypt AES_ecb_encrypt +#define ossl_aes_cbc_encrypt AES_cbc_encrypt +#define ossl_aes_cfb128_encrypt AES_cfb128_encrypt +#define ossl_aes_cfb1_encrypt AES_cfb1_encrypt +#define ossl_aes_cfb8_encrypt AES_cfb8_encrypt +#define ossl_aes_ofb128_encrypt AES_ofb128_encrypt +#define ossl_aes_ctr128_encrypt AES_ctr128_encrypt +#define ossl_aes_ige_encrypt AES_ige_encrypt +#define ossl_aes_bi_ige_encrypt AES_bi_ige_encrypt +#define ossl_aes_wrap_key +#define ossl_aes_unwrap_key + +#else +#define _OSSL_DLL +#endif +#include + +#define AES_ENCRYPT 1 +#define AES_DECRYPT 0 + +/* +Because array size can't be a const in C, the following two are macros. +Both sizes are in bytes. +@remark: +#1.AES_BLOCK_SIZE can be 32 + +#2.The iv equals AES_BLOCK_SIZE always + +#3.AES KEY also can be 128bits or 256bits +*/ +#define AES_MAXNR 14 +#define AES_BLOCK_SIZE 16 + +#if _HAS_OSSL +#ifdef __cplusplus +extern "C" { +#endif +#endif + + /* This should be a hidden type, but EVP requires that the size be known */ + struct aes_key_st { +#ifdef AES_LONG + unsigned long rd_key[4 *(AES_MAXNR + 1)]; +#else + unsigned int rd_key[4 *(AES_MAXNR + 1)]; +#endif + int rounds; + }; + typedef struct aes_key_st AES_KEY; + + // const char *ossl_aes_options(void); + + _OSSL_DLL int ossl_aes_set_encrypt_key(const unsigned char *userKey, const int bits, + AES_KEY *key); + _OSSL_DLL int ossl_aes_set_decrypt_key(const unsigned char *userKey, const int bits, + AES_KEY *key); + + _OSSL_DLL void ossl_aes_encrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key); + _OSSL_DLL void ossl_aes_decrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key); + + _OSSL_DLL void ossl_aes_ecb_encrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key, const int enc); + _OSSL_DLL void ossl_aes_cbc_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + unsigned char *ivec, const int enc); + _OSSL_DLL void ossl_aes_cfb128_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + unsigned char *ivec, int *num, const int enc); + _OSSL_DLL void ossl_aes_cfb1_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + unsigned char *ivec, int *num, const int enc); + _OSSL_DLL void ossl_aes_cfb8_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + unsigned char *ivec, int *num, const int enc); + _OSSL_DLL void ossl_aes_ofb128_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + unsigned char *ivec, int *num); + _OSSL_DLL void ossl_aes_ctr128_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + unsigned char ivec[AES_BLOCK_SIZE], + unsigned char ecount_buf[AES_BLOCK_SIZE], + unsigned int *num); + /* NB: the IV is _two_ blocks long */ + _OSSL_DLL void ossl_aes_ige_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + unsigned char *ivec, const int enc); + /* NB: the IV is _four_ blocks long */ + _OSSL_DLL void ossl_aes_bi_ige_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + const AES_KEY *key2, const unsigned char *ivec, + const int enc); + // + //_OSSL_DLL int ossl_aes_wrap_key(AES_KEY *key, const unsigned char *iv, + // unsigned char *out, + // const unsigned char *in, unsigned int inlen); + //_OSSL_DLL int ossl_aes_unwrap_key(AES_KEY *key, const unsigned char *iv, + // unsigned char *out, + // const unsigned char *in, unsigned int inlen); + +#if _HAS_OSSL +#ifdef __cplusplus +} +#endif +#endif + +#endif /* !HEADER_AES_H */ diff --git a/src/aes_core.cpp b/src/aes_core.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b292405bd19824c7df50dab39ca8ab595e41f125 --- /dev/null +++ b/src/aes_core.cpp @@ -0,0 +1,2594 @@ +/* crypto/aes/aes_core.c -*- mode:C; c-file-style: "eay" -*- */ +/** + * rijndael-alg-fst.c + * + * @version 3.0 (December 2000) + * + * Optimised ANSI C code for the Rijndael cipher (now AES) + * + * @author Vincent Rijmen + * @author Antoon Bosselaers + * @author Paulo Barreto + * + * This code is hereby placed in the public domain. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Note: rewritten a little bit to provide error control and an OpenSSL- + compatible API */ +#ifndef AES_DEBUG +# ifndef NDEBUG +# define NDEBUG +# endif +#endif +#include + +#include +#include "aes.h" + +#if _HAS_OSSL +#pragma comment(lib, "libeay32.lib") +#else + +/* crypto/aes/aes_locl.h -*- mode:C; c-file-style: "eay" -*- */ +/* ==================================================================== +* Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* +* 3. All advertising materials mentioning features or use of this +* software must display the following acknowledgment: +* "This product includes software developed by the OpenSSL Project +* for use in the OpenSSL Toolkit. (http://www.openssl.org/)" +* +* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to +* endorse or promote products derived from this software without +* prior written permission. For written permission, please contact +* openssl-core@openssl.org. +* +* 5. Products derived from this software may not be called "OpenSSL" +* nor may "OpenSSL" appear in their names without prior written +* permission of the OpenSSL Project. +* +* 6. Redistributions of any form whatsoever must retain the following +* acknowledgment: +* "This product includes software developed by the OpenSSL Project +* for use in the OpenSSL Toolkit (http://www.openssl.org/)" +* +* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY +* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR +* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +* OF THE POSSIBILITY OF SUCH DAMAGE. +* ==================================================================== +* +*/ + +#ifndef HEADER_AES_LOCL_H +#define HEADER_AES_LOCL_H + +//#include + +#ifdef OPENSSL_NO_AES +#error AES is disabled. +#endif + +#include +#include +#include + +#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64)) +# define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00) +# define GETU32(p) SWAP(*((u32 *)(p))) +# define PUTU32(ct, st) { *((u32 *)(ct)) = SWAP((st)); } +#else +# define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] << 8) ^ ((u32)(pt)[3])) +# define PUTU32(ct, st) { (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); (ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); } +#endif + +#ifdef AES_LONG +typedef unsigned long u32; +#else +typedef unsigned int u32; +#endif +typedef unsigned short u16; +typedef unsigned char u8; + +#define MAXKC (256/32) +#define MAXKB (256/8) +#define MAXNR 14 + +/* This controls loop-unrolling in aes_core.c */ +#undef FULL_UNROLL + +#endif /* !HEADER_AES_LOCL_H */ + + +#ifndef AES_ASM +/* +Te0[x] = S [x].[02, 01, 01, 03]; +Te1[x] = S [x].[03, 02, 01, 01]; +Te2[x] = S [x].[01, 03, 02, 01]; +Te3[x] = S [x].[01, 01, 03, 02]; + +Td0[x] = Si[x].[0e, 09, 0d, 0b]; +Td1[x] = Si[x].[0b, 0e, 09, 0d]; +Td2[x] = Si[x].[0d, 0b, 0e, 09]; +Td3[x] = Si[x].[09, 0d, 0b, 0e]; +Td4[x] = Si[x].[01]; +*/ + +static const u32 Te0[256] = { + 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, + 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U, + 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU, + 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU, + 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U, + 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU, + 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU, + 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU, + 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU, + 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU, + 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U, + 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU, + 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU, + 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U, + 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU, + 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU, + 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU, + 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU, + 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU, + 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U, + 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU, + 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU, + 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU, + 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU, + 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U, + 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U, + 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U, + 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U, + 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU, + 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U, + 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U, + 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU, + 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU, + 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U, + 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U, + 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U, + 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU, + 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U, + 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU, + 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U, + 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU, + 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U, + 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U, + 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU, + 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U, + 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U, + 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U, + 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U, + 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U, + 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U, + 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U, + 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U, + 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU, + 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U, + 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U, + 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U, + 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U, + 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U, + 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U, + 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU, + 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U, + 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U, + 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U, + 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU, +}; +static const u32 Te1[256] = { + 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU, + 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U, + 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU, + 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U, + 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU, + 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U, + 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU, + 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U, + 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U, + 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU, + 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U, + 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U, + 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U, + 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU, + 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U, + 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U, + 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU, + 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U, + 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U, + 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U, + 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU, + 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU, + 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U, + 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU, + 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU, + 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U, + 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU, + 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U, + 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU, + 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U, + 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U, + 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U, + 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU, + 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U, + 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU, + 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U, + 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU, + 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U, + 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U, + 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU, + 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU, + 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU, + 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U, + 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U, + 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU, + 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U, + 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU, + 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U, + 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU, + 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U, + 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU, + 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU, + 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U, + 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU, + 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U, + 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU, + 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U, + 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U, + 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U, + 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU, + 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU, + 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U, + 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU, + 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U, +}; +static const u32 Te2[256] = { + 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU, + 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U, + 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU, + 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U, + 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU, + 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U, + 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU, + 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U, + 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U, + 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU, + 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U, + 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U, + 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U, + 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU, + 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U, + 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U, + 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU, + 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U, + 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U, + 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U, + 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU, + 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU, + 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U, + 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU, + 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU, + 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U, + 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU, + 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U, + 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU, + 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U, + 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U, + 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U, + 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU, + 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U, + 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU, + 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U, + 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU, + 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U, + 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U, + 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU, + 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU, + 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU, + 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U, + 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U, + 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU, + 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U, + 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU, + 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U, + 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU, + 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U, + 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU, + 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU, + 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U, + 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU, + 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U, + 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU, + 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U, + 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U, + 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U, + 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU, + 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU, + 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U, + 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU, + 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U, +}; +static const u32 Te3[256] = { + 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U, + 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U, + 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U, + 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU, + 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU, + 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU, + 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U, + 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU, + 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU, + 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U, + 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U, + 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU, + 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU, + 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU, + 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU, + 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU, + 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U, + 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU, + 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU, + 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U, + 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U, + 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U, + 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U, + 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U, + 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU, + 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U, + 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU, + 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU, + 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U, + 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U, + 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U, + 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU, + 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U, + 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU, + 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU, + 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U, + 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U, + 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU, + 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U, + 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU, + 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U, + 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U, + 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U, + 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U, + 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU, + 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U, + 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU, + 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U, + 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU, + 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U, + 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU, + 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU, + 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU, + 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU, + 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U, + 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U, + 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U, + 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U, + 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U, + 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U, + 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU, + 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U, + 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU, + 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU, +}; + +static const u32 Td0[256] = { + 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U, + 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U, + 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U, + 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU, + 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U, + 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U, + 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU, + 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U, + 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU, + 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U, + 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U, + 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U, + 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U, + 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU, + 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U, + 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU, + 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U, + 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU, + 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U, + 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U, + 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U, + 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU, + 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U, + 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU, + 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U, + 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU, + 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U, + 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU, + 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU, + 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U, + 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU, + 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U, + 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU, + 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U, + 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U, + 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U, + 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU, + 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U, + 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U, + 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU, + 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U, + 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U, + 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U, + 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U, + 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U, + 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU, + 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U, + 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U, + 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U, + 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U, + 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U, + 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU, + 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU, + 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU, + 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU, + 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U, + 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U, + 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU, + 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU, + 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U, + 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU, + 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U, + 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U, + 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U, +}; +static const u32 Td1[256] = { + 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU, + 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U, + 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU, + 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U, + 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U, + 0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U, + 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U, + 0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U, + 0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U, + 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU, + 0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU, + 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU, + 0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U, + 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU, + 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U, + 0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U, + 0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U, + 0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU, + 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU, + 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U, + 0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU, + 0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U, + 0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU, + 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU, + 0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U, + 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U, + 0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U, + 0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU, + 0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U, + 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU, + 0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U, + 0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U, + 0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U, + 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU, + 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U, + 0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U, + 0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U, + 0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U, + 0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U, + 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U, + 0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU, + 0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU, + 0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U, + 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU, + 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U, + 0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU, + 0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU, + 0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U, + 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU, + 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U, + 0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U, + 0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U, + 0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U, + 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U, + 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U, + 0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U, + 0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU, + 0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U, + 0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U, + 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU, + 0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U, + 0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U, + 0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U, + 0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U, +}; +static const u32 Td2[256] = { + 0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U, + 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U, + 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U, + 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U, + 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU, + 0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U, + 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U, + 0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U, + 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U, + 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU, + 0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U, + 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U, + 0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU, + 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U, + 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U, + 0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U, + 0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U, + 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U, + 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U, + 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU, + 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U, + 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U, + 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U, + 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U, + 0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U, + 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU, + 0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU, + 0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U, + 0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU, + 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U, + 0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU, + 0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU, + 0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU, + 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU, + 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U, + 0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U, + 0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U, + 0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U, + 0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U, + 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U, + 0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U, + 0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU, + 0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU, + 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U, + 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U, + 0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU, + 0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU, + 0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U, + 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U, + 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U, + 0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U, + 0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U, + 0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U, + 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U, + 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU, + 0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U, + 0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U, + 0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U, + 0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U, + 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U, + 0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U, + 0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU, + 0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U, + 0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U, +}; +static const u32 Td3[256] = { + 0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU, + 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU, + 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U, + 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U, + 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU, + 0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU, + 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U, + 0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU, + 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U, + 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU, + 0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U, + 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U, + 0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U, + 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U, + 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U, + 0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU, + 0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU, + 0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U, + 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U, + 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU, + 0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU, + 0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U, + 0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U, + 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U, + 0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U, + 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU, + 0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U, + 0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U, + 0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU, + 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU, + 0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U, + 0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U, + 0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U, + 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU, + 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U, + 0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U, + 0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U, + 0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U, + 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U, + 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U, + 0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U, + 0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU, + 0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U, + 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U, + 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU, + 0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU, + 0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U, + 0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU, + 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U, + 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U, + 0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U, + 0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U, + 0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U, + 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U, + 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU, + 0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU, + 0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU, + 0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU, + 0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U, + 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U, + 0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U, + 0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU, + 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U, + 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U, +}; +static const u8 Td4[256] = { + 0x52U, 0x09U, 0x6aU, 0xd5U, 0x30U, 0x36U, 0xa5U, 0x38U, + 0xbfU, 0x40U, 0xa3U, 0x9eU, 0x81U, 0xf3U, 0xd7U, 0xfbU, + 0x7cU, 0xe3U, 0x39U, 0x82U, 0x9bU, 0x2fU, 0xffU, 0x87U, + 0x34U, 0x8eU, 0x43U, 0x44U, 0xc4U, 0xdeU, 0xe9U, 0xcbU, + 0x54U, 0x7bU, 0x94U, 0x32U, 0xa6U, 0xc2U, 0x23U, 0x3dU, + 0xeeU, 0x4cU, 0x95U, 0x0bU, 0x42U, 0xfaU, 0xc3U, 0x4eU, + 0x08U, 0x2eU, 0xa1U, 0x66U, 0x28U, 0xd9U, 0x24U, 0xb2U, + 0x76U, 0x5bU, 0xa2U, 0x49U, 0x6dU, 0x8bU, 0xd1U, 0x25U, + 0x72U, 0xf8U, 0xf6U, 0x64U, 0x86U, 0x68U, 0x98U, 0x16U, + 0xd4U, 0xa4U, 0x5cU, 0xccU, 0x5dU, 0x65U, 0xb6U, 0x92U, + 0x6cU, 0x70U, 0x48U, 0x50U, 0xfdU, 0xedU, 0xb9U, 0xdaU, + 0x5eU, 0x15U, 0x46U, 0x57U, 0xa7U, 0x8dU, 0x9dU, 0x84U, + 0x90U, 0xd8U, 0xabU, 0x00U, 0x8cU, 0xbcU, 0xd3U, 0x0aU, + 0xf7U, 0xe4U, 0x58U, 0x05U, 0xb8U, 0xb3U, 0x45U, 0x06U, + 0xd0U, 0x2cU, 0x1eU, 0x8fU, 0xcaU, 0x3fU, 0x0fU, 0x02U, + 0xc1U, 0xafU, 0xbdU, 0x03U, 0x01U, 0x13U, 0x8aU, 0x6bU, + 0x3aU, 0x91U, 0x11U, 0x41U, 0x4fU, 0x67U, 0xdcU, 0xeaU, + 0x97U, 0xf2U, 0xcfU, 0xceU, 0xf0U, 0xb4U, 0xe6U, 0x73U, + 0x96U, 0xacU, 0x74U, 0x22U, 0xe7U, 0xadU, 0x35U, 0x85U, + 0xe2U, 0xf9U, 0x37U, 0xe8U, 0x1cU, 0x75U, 0xdfU, 0x6eU, + 0x47U, 0xf1U, 0x1aU, 0x71U, 0x1dU, 0x29U, 0xc5U, 0x89U, + 0x6fU, 0xb7U, 0x62U, 0x0eU, 0xaaU, 0x18U, 0xbeU, 0x1bU, + 0xfcU, 0x56U, 0x3eU, 0x4bU, 0xc6U, 0xd2U, 0x79U, 0x20U, + 0x9aU, 0xdbU, 0xc0U, 0xfeU, 0x78U, 0xcdU, 0x5aU, 0xf4U, + 0x1fU, 0xddU, 0xa8U, 0x33U, 0x88U, 0x07U, 0xc7U, 0x31U, + 0xb1U, 0x12U, 0x10U, 0x59U, 0x27U, 0x80U, 0xecU, 0x5fU, + 0x60U, 0x51U, 0x7fU, 0xa9U, 0x19U, 0xb5U, 0x4aU, 0x0dU, + 0x2dU, 0xe5U, 0x7aU, 0x9fU, 0x93U, 0xc9U, 0x9cU, 0xefU, + 0xa0U, 0xe0U, 0x3bU, 0x4dU, 0xaeU, 0x2aU, 0xf5U, 0xb0U, + 0xc8U, 0xebU, 0xbbU, 0x3cU, 0x83U, 0x53U, 0x99U, 0x61U, + 0x17U, 0x2bU, 0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U, 0x26U, + 0xe1U, 0x69U, 0x14U, 0x63U, 0x55U, 0x21U, 0x0cU, 0x7dU, +}; +static const u32 rcon[] = { + 0x01000000, 0x02000000, 0x04000000, 0x08000000, + 0x10000000, 0x20000000, 0x40000000, 0x80000000, + 0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ +}; + +/** + * Expand the cipher key into the encryption key schedule. + */ +int ossl_aes_set_encrypt_key(const unsigned char *userKey, const int bits, + AES_KEY *key) { + + u32 *rk; + int i = 0; + u32 temp; + + if (!userKey || !key) + return -1; + if (bits != 128 && bits != 192 && bits != 256) + return -2; + + rk = key->rd_key; + + if (bits==128) + key->rounds = 10; + else if (bits==192) + key->rounds = 12; + else + key->rounds = 14; + + rk[0] = GETU32(userKey ); + rk[1] = GETU32(userKey + 4); + rk[2] = GETU32(userKey + 8); + rk[3] = GETU32(userKey + 12); + if (bits == 128) { + while (1) { + temp = rk[3]; + rk[4] = rk[0] ^ + (Te2[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te3[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te0[(temp ) & 0xff] & 0x0000ff00) ^ + (Te1[(temp >> 24) ] & 0x000000ff) ^ + rcon[i]; + rk[5] = rk[1] ^ rk[4]; + rk[6] = rk[2] ^ rk[5]; + rk[7] = rk[3] ^ rk[6]; + if (++i == 10) { + return 0; + } + rk += 4; + } + } + rk[4] = GETU32(userKey + 16); + rk[5] = GETU32(userKey + 20); + if (bits == 192) { + while (1) { + temp = rk[ 5]; + rk[ 6] = rk[ 0] ^ + (Te2[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te3[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te0[(temp ) & 0xff] & 0x0000ff00) ^ + (Te1[(temp >> 24) ] & 0x000000ff) ^ + rcon[i]; + rk[ 7] = rk[ 1] ^ rk[ 6]; + rk[ 8] = rk[ 2] ^ rk[ 7]; + rk[ 9] = rk[ 3] ^ rk[ 8]; + if (++i == 8) { + return 0; + } + rk[10] = rk[ 4] ^ rk[ 9]; + rk[11] = rk[ 5] ^ rk[10]; + rk += 6; + } + } + rk[6] = GETU32(userKey + 24); + rk[7] = GETU32(userKey + 28); + if (bits == 256) { + while (1) { + temp = rk[ 7]; + rk[ 8] = rk[ 0] ^ + (Te2[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te3[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te0[(temp ) & 0xff] & 0x0000ff00) ^ + (Te1[(temp >> 24) ] & 0x000000ff) ^ + rcon[i]; + rk[ 9] = rk[ 1] ^ rk[ 8]; + rk[10] = rk[ 2] ^ rk[ 9]; + rk[11] = rk[ 3] ^ rk[10]; + if (++i == 7) { + return 0; + } + temp = rk[11]; + rk[12] = rk[ 4] ^ + (Te2[(temp >> 24) ] & 0xff000000) ^ + (Te3[(temp >> 16) & 0xff] & 0x00ff0000) ^ + (Te0[(temp >> 8) & 0xff] & 0x0000ff00) ^ + (Te1[(temp ) & 0xff] & 0x000000ff); + rk[13] = rk[ 5] ^ rk[12]; + rk[14] = rk[ 6] ^ rk[13]; + rk[15] = rk[ 7] ^ rk[14]; + + rk += 8; + } + } + return 0; +} + +/** + * Expand the cipher key into the decryption key schedule. + */ +int ossl_aes_set_decrypt_key(const unsigned char *userKey, const int bits, + AES_KEY *key) { + + u32 *rk; + int i, j, status; + u32 temp; + + /* first, start with an encryption schedule */ + status = ossl_aes_set_encrypt_key(userKey, bits, key); + if (status < 0) + return status; + + rk = key->rd_key; + + /* invert the order of the round keys: */ + for (i = 0, j = 4*(key->rounds); i < j; i += 4, j -= 4) { + temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp; + temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp; + temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp; + temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp; + } + /* apply the inverse MixColumn transform to all round keys but the first and the last: */ + for (i = 1; i < (key->rounds); i++) { + rk += 4; + rk[0] = + Td0[Te1[(rk[0] >> 24) ] & 0xff] ^ + Td1[Te1[(rk[0] >> 16) & 0xff] & 0xff] ^ + Td2[Te1[(rk[0] >> 8) & 0xff] & 0xff] ^ + Td3[Te1[(rk[0] ) & 0xff] & 0xff]; + rk[1] = + Td0[Te1[(rk[1] >> 24) ] & 0xff] ^ + Td1[Te1[(rk[1] >> 16) & 0xff] & 0xff] ^ + Td2[Te1[(rk[1] >> 8) & 0xff] & 0xff] ^ + Td3[Te1[(rk[1] ) & 0xff] & 0xff]; + rk[2] = + Td0[Te1[(rk[2] >> 24) ] & 0xff] ^ + Td1[Te1[(rk[2] >> 16) & 0xff] & 0xff] ^ + Td2[Te1[(rk[2] >> 8) & 0xff] & 0xff] ^ + Td3[Te1[(rk[2] ) & 0xff] & 0xff]; + rk[3] = + Td0[Te1[(rk[3] >> 24) ] & 0xff] ^ + Td1[Te1[(rk[3] >> 16) & 0xff] & 0xff] ^ + Td2[Te1[(rk[3] >> 8) & 0xff] & 0xff] ^ + Td3[Te1[(rk[3] ) & 0xff] & 0xff]; + } + return 0; +} + +/* + * Encrypt a single block + * in and out can overlap + */ +void ossl_aes_encrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key) { + + const u32 *rk; + u32 s0, s1, s2, s3, t0, t1, t2, t3; +#ifndef FULL_UNROLL + int r; +#endif /* ?FULL_UNROLL */ + + assert(in && out && key); + rk = key->rd_key; + + /* + * map byte array block to cipher state + * and add initial round key: + */ + s0 = GETU32(in ) ^ rk[0]; + s1 = GETU32(in + 4) ^ rk[1]; + s2 = GETU32(in + 8) ^ rk[2]; + s3 = GETU32(in + 12) ^ rk[3]; +#ifdef FULL_UNROLL + /* round 1: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7]; + /* round 2: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11]; + /* round 3: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15]; + /* round 4: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19]; + /* round 5: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23]; + /* round 6: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27]; + /* round 7: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31]; + /* round 8: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35]; + /* round 9: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39]; + if (key->rounds > 10) { + /* round 10: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[41]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[42]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[43]; + /* round 11: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[44]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[45]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[46]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[47]; + if (key->rounds > 12) { + /* round 12: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[48]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[49]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[50]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[51]; + /* round 13: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[52]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[53]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[54]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[55]; + } + } + rk += key->rounds << 2; +#else /* !FULL_UNROLL */ + /* + * Nr - 1 full rounds: + */ + r = key->rounds >> 1; + for (;;) { + t0 = + Te0[(s0 >> 24) ] ^ + Te1[(s1 >> 16) & 0xff] ^ + Te2[(s2 >> 8) & 0xff] ^ + Te3[(s3 ) & 0xff] ^ + rk[4]; + t1 = + Te0[(s1 >> 24) ] ^ + Te1[(s2 >> 16) & 0xff] ^ + Te2[(s3 >> 8) & 0xff] ^ + Te3[(s0 ) & 0xff] ^ + rk[5]; + t2 = + Te0[(s2 >> 24) ] ^ + Te1[(s3 >> 16) & 0xff] ^ + Te2[(s0 >> 8) & 0xff] ^ + Te3[(s1 ) & 0xff] ^ + rk[6]; + t3 = + Te0[(s3 >> 24) ] ^ + Te1[(s0 >> 16) & 0xff] ^ + Te2[(s1 >> 8) & 0xff] ^ + Te3[(s2 ) & 0xff] ^ + rk[7]; + + rk += 8; + if (--r == 0) { + break; + } + + s0 = + Te0[(t0 >> 24) ] ^ + Te1[(t1 >> 16) & 0xff] ^ + Te2[(t2 >> 8) & 0xff] ^ + Te3[(t3 ) & 0xff] ^ + rk[0]; + s1 = + Te0[(t1 >> 24) ] ^ + Te1[(t2 >> 16) & 0xff] ^ + Te2[(t3 >> 8) & 0xff] ^ + Te3[(t0 ) & 0xff] ^ + rk[1]; + s2 = + Te0[(t2 >> 24) ] ^ + Te1[(t3 >> 16) & 0xff] ^ + Te2[(t0 >> 8) & 0xff] ^ + Te3[(t1 ) & 0xff] ^ + rk[2]; + s3 = + Te0[(t3 >> 24) ] ^ + Te1[(t0 >> 16) & 0xff] ^ + Te2[(t1 >> 8) & 0xff] ^ + Te3[(t2 ) & 0xff] ^ + rk[3]; + } +#endif /* ?FULL_UNROLL */ + /* + * apply last round and + * map cipher state to byte array block: + */ + s0 = + (Te2[(t0 >> 24) ] & 0xff000000) ^ + (Te3[(t1 >> 16) & 0xff] & 0x00ff0000) ^ + (Te0[(t2 >> 8) & 0xff] & 0x0000ff00) ^ + (Te1[(t3 ) & 0xff] & 0x000000ff) ^ + rk[0]; + PUTU32(out , s0); + s1 = + (Te2[(t1 >> 24) ] & 0xff000000) ^ + (Te3[(t2 >> 16) & 0xff] & 0x00ff0000) ^ + (Te0[(t3 >> 8) & 0xff] & 0x0000ff00) ^ + (Te1[(t0 ) & 0xff] & 0x000000ff) ^ + rk[1]; + PUTU32(out + 4, s1); + s2 = + (Te2[(t2 >> 24) ] & 0xff000000) ^ + (Te3[(t3 >> 16) & 0xff] & 0x00ff0000) ^ + (Te0[(t0 >> 8) & 0xff] & 0x0000ff00) ^ + (Te1[(t1 ) & 0xff] & 0x000000ff) ^ + rk[2]; + PUTU32(out + 8, s2); + s3 = + (Te2[(t3 >> 24) ] & 0xff000000) ^ + (Te3[(t0 >> 16) & 0xff] & 0x00ff0000) ^ + (Te0[(t1 >> 8) & 0xff] & 0x0000ff00) ^ + (Te1[(t2 ) & 0xff] & 0x000000ff) ^ + rk[3]; + PUTU32(out + 12, s3); +} + +/* + * Decrypt a single block + * in and out can overlap + */ +void ossl_aes_decrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key) { + + const u32 *rk; + u32 s0, s1, s2, s3, t0, t1, t2, t3; +#ifndef FULL_UNROLL + int r; +#endif /* ?FULL_UNROLL */ + + assert(in && out && key); + rk = key->rd_key; + + /* + * map byte array block to cipher state + * and add initial round key: + */ + s0 = GETU32(in ) ^ rk[0]; + s1 = GETU32(in + 4) ^ rk[1]; + s2 = GETU32(in + 8) ^ rk[2]; + s3 = GETU32(in + 12) ^ rk[3]; +#ifdef FULL_UNROLL + /* round 1: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[ 4]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[ 5]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[ 6]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[ 7]; + /* round 2: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[ 8]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[ 9]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[10]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[11]; + /* round 3: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[12]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[13]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[14]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[15]; + /* round 4: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[16]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[17]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[18]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[19]; + /* round 5: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[20]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[21]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[22]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[23]; + /* round 6: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[24]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[25]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[26]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[27]; + /* round 7: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[28]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[29]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[30]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[31]; + /* round 8: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[32]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[33]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[34]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[35]; + /* round 9: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[36]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[37]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[38]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[39]; + if (key->rounds > 10) { + /* round 10: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[40]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[41]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[42]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[43]; + /* round 11: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[44]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[45]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[46]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[47]; + if (key->rounds > 12) { + /* round 12: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[48]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[49]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[50]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[51]; + /* round 13: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[52]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[53]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[54]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[55]; + } + } + rk += key->rounds << 2; +#else /* !FULL_UNROLL */ + /* + * Nr - 1 full rounds: + */ + r = key->rounds >> 1; + for (;;) { + t0 = + Td0[(s0 >> 24) ] ^ + Td1[(s3 >> 16) & 0xff] ^ + Td2[(s2 >> 8) & 0xff] ^ + Td3[(s1 ) & 0xff] ^ + rk[4]; + t1 = + Td0[(s1 >> 24) ] ^ + Td1[(s0 >> 16) & 0xff] ^ + Td2[(s3 >> 8) & 0xff] ^ + Td3[(s2 ) & 0xff] ^ + rk[5]; + t2 = + Td0[(s2 >> 24) ] ^ + Td1[(s1 >> 16) & 0xff] ^ + Td2[(s0 >> 8) & 0xff] ^ + Td3[(s3 ) & 0xff] ^ + rk[6]; + t3 = + Td0[(s3 >> 24) ] ^ + Td1[(s2 >> 16) & 0xff] ^ + Td2[(s1 >> 8) & 0xff] ^ + Td3[(s0 ) & 0xff] ^ + rk[7]; + + rk += 8; + if (--r == 0) { + break; + } + + s0 = + Td0[(t0 >> 24) ] ^ + Td1[(t3 >> 16) & 0xff] ^ + Td2[(t2 >> 8) & 0xff] ^ + Td3[(t1 ) & 0xff] ^ + rk[0]; + s1 = + Td0[(t1 >> 24) ] ^ + Td1[(t0 >> 16) & 0xff] ^ + Td2[(t3 >> 8) & 0xff] ^ + Td3[(t2 ) & 0xff] ^ + rk[1]; + s2 = + Td0[(t2 >> 24) ] ^ + Td1[(t1 >> 16) & 0xff] ^ + Td2[(t0 >> 8) & 0xff] ^ + Td3[(t3 ) & 0xff] ^ + rk[2]; + s3 = + Td0[(t3 >> 24) ] ^ + Td1[(t2 >> 16) & 0xff] ^ + Td2[(t1 >> 8) & 0xff] ^ + Td3[(t0 ) & 0xff] ^ + rk[3]; + } +#endif /* ?FULL_UNROLL */ + /* + * apply last round and + * map cipher state to byte array block: + */ + s0 = + (Td4[(t0 >> 24) ] << 24) ^ + (Td4[(t3 >> 16) & 0xff] << 16) ^ + (Td4[(t2 >> 8) & 0xff] << 8) ^ + (Td4[(t1 ) & 0xff]) ^ + rk[0]; + PUTU32(out , s0); + s1 = + (Td4[(t1 >> 24) ] << 24) ^ + (Td4[(t0 >> 16) & 0xff] << 16) ^ + (Td4[(t3 >> 8) & 0xff] << 8) ^ + (Td4[(t2 ) & 0xff]) ^ + rk[1]; + PUTU32(out + 4, s1); + s2 = + (Td4[(t2 >> 24) ] << 24) ^ + (Td4[(t1 >> 16) & 0xff] << 16) ^ + (Td4[(t0 >> 8) & 0xff] << 8) ^ + (Td4[(t3 ) & 0xff]) ^ + rk[2]; + PUTU32(out + 8, s2); + s3 = + (Td4[(t3 >> 24) ] << 24) ^ + (Td4[(t2 >> 16) & 0xff] << 16) ^ + (Td4[(t1 >> 8) & 0xff] << 8) ^ + (Td4[(t0 ) & 0xff]) ^ + rk[3]; + PUTU32(out + 12, s3); +} + +#else /* AES_ASM */ + +static const u8 Te4[256] = { + 0x63U, 0x7cU, 0x77U, 0x7bU, 0xf2U, 0x6bU, 0x6fU, 0xc5U, + 0x30U, 0x01U, 0x67U, 0x2bU, 0xfeU, 0xd7U, 0xabU, 0x76U, + 0xcaU, 0x82U, 0xc9U, 0x7dU, 0xfaU, 0x59U, 0x47U, 0xf0U, + 0xadU, 0xd4U, 0xa2U, 0xafU, 0x9cU, 0xa4U, 0x72U, 0xc0U, + 0xb7U, 0xfdU, 0x93U, 0x26U, 0x36U, 0x3fU, 0xf7U, 0xccU, + 0x34U, 0xa5U, 0xe5U, 0xf1U, 0x71U, 0xd8U, 0x31U, 0x15U, + 0x04U, 0xc7U, 0x23U, 0xc3U, 0x18U, 0x96U, 0x05U, 0x9aU, + 0x07U, 0x12U, 0x80U, 0xe2U, 0xebU, 0x27U, 0xb2U, 0x75U, + 0x09U, 0x83U, 0x2cU, 0x1aU, 0x1bU, 0x6eU, 0x5aU, 0xa0U, + 0x52U, 0x3bU, 0xd6U, 0xb3U, 0x29U, 0xe3U, 0x2fU, 0x84U, + 0x53U, 0xd1U, 0x00U, 0xedU, 0x20U, 0xfcU, 0xb1U, 0x5bU, + 0x6aU, 0xcbU, 0xbeU, 0x39U, 0x4aU, 0x4cU, 0x58U, 0xcfU, + 0xd0U, 0xefU, 0xaaU, 0xfbU, 0x43U, 0x4dU, 0x33U, 0x85U, + 0x45U, 0xf9U, 0x02U, 0x7fU, 0x50U, 0x3cU, 0x9fU, 0xa8U, + 0x51U, 0xa3U, 0x40U, 0x8fU, 0x92U, 0x9dU, 0x38U, 0xf5U, + 0xbcU, 0xb6U, 0xdaU, 0x21U, 0x10U, 0xffU, 0xf3U, 0xd2U, + 0xcdU, 0x0cU, 0x13U, 0xecU, 0x5fU, 0x97U, 0x44U, 0x17U, + 0xc4U, 0xa7U, 0x7eU, 0x3dU, 0x64U, 0x5dU, 0x19U, 0x73U, + 0x60U, 0x81U, 0x4fU, 0xdcU, 0x22U, 0x2aU, 0x90U, 0x88U, + 0x46U, 0xeeU, 0xb8U, 0x14U, 0xdeU, 0x5eU, 0x0bU, 0xdbU, + 0xe0U, 0x32U, 0x3aU, 0x0aU, 0x49U, 0x06U, 0x24U, 0x5cU, + 0xc2U, 0xd3U, 0xacU, 0x62U, 0x91U, 0x95U, 0xe4U, 0x79U, + 0xe7U, 0xc8U, 0x37U, 0x6dU, 0x8dU, 0xd5U, 0x4eU, 0xa9U, + 0x6cU, 0x56U, 0xf4U, 0xeaU, 0x65U, 0x7aU, 0xaeU, 0x08U, + 0xbaU, 0x78U, 0x25U, 0x2eU, 0x1cU, 0xa6U, 0xb4U, 0xc6U, + 0xe8U, 0xddU, 0x74U, 0x1fU, 0x4bU, 0xbdU, 0x8bU, 0x8aU, + 0x70U, 0x3eU, 0xb5U, 0x66U, 0x48U, 0x03U, 0xf6U, 0x0eU, + 0x61U, 0x35U, 0x57U, 0xb9U, 0x86U, 0xc1U, 0x1dU, 0x9eU, + 0xe1U, 0xf8U, 0x98U, 0x11U, 0x69U, 0xd9U, 0x8eU, 0x94U, + 0x9bU, 0x1eU, 0x87U, 0xe9U, 0xceU, 0x55U, 0x28U, 0xdfU, + 0x8cU, 0xa1U, 0x89U, 0x0dU, 0xbfU, 0xe6U, 0x42U, 0x68U, + 0x41U, 0x99U, 0x2dU, 0x0fU, 0xb0U, 0x54U, 0xbbU, 0x16U +}; +static const u32 rcon[] = { + 0x01000000, 0x02000000, 0x04000000, 0x08000000, + 0x10000000, 0x20000000, 0x40000000, 0x80000000, + 0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ +}; + +/** + * Expand the cipher key into the encryption key schedule. + */ +int ossl_aes_set_encrypt_key(const unsigned char *userKey, const int bits, + AES_KEY *key) { + u32 *rk; + int i = 0; + u32 temp; + + if (!userKey || !key) + return -1; + if (bits != 128 && bits != 192 && bits != 256) + return -2; + + rk = key->rd_key; + + if (bits==128) + key->rounds = 10; + else if (bits==192) + key->rounds = 12; + else + key->rounds = 14; + + rk[0] = GETU32(userKey ); + rk[1] = GETU32(userKey + 4); + rk[2] = GETU32(userKey + 8); + rk[3] = GETU32(userKey + 12); + if (bits == 128) { + while (1) { + temp = rk[3]; + rk[4] = rk[0] ^ + (Te4[(temp >> 16) & 0xff] << 24) ^ + (Te4[(temp >> 8) & 0xff] << 16) ^ + (Te4[(temp ) & 0xff] << 8) ^ + (Te4[(temp >> 24) ]) ^ + rcon[i]; + rk[5] = rk[1] ^ rk[4]; + rk[6] = rk[2] ^ rk[5]; + rk[7] = rk[3] ^ rk[6]; + if (++i == 10) { + return 0; + } + rk += 4; + } + } + rk[4] = GETU32(userKey + 16); + rk[5] = GETU32(userKey + 20); + if (bits == 192) { + while (1) { + temp = rk[ 5]; + rk[ 6] = rk[ 0] ^ + (Te4[(temp >> 16) & 0xff] << 24) ^ + (Te4[(temp >> 8) & 0xff] << 16) ^ + (Te4[(temp ) & 0xff] << 8) ^ + (Te4[(temp >> 24) ]) ^ + rcon[i]; + rk[ 7] = rk[ 1] ^ rk[ 6]; + rk[ 8] = rk[ 2] ^ rk[ 7]; + rk[ 9] = rk[ 3] ^ rk[ 8]; + if (++i == 8) { + return 0; + } + rk[10] = rk[ 4] ^ rk[ 9]; + rk[11] = rk[ 5] ^ rk[10]; + rk += 6; + } + } + rk[6] = GETU32(userKey + 24); + rk[7] = GETU32(userKey + 28); + if (bits == 256) { + while (1) { + temp = rk[ 7]; + rk[ 8] = rk[ 0] ^ + (Te4[(temp >> 16) & 0xff] << 24) ^ + (Te4[(temp >> 8) & 0xff] << 16) ^ + (Te4[(temp ) & 0xff] << 8) ^ + (Te4[(temp >> 24) ]) ^ + rcon[i]; + rk[ 9] = rk[ 1] ^ rk[ 8]; + rk[10] = rk[ 2] ^ rk[ 9]; + rk[11] = rk[ 3] ^ rk[10]; + if (++i == 7) { + return 0; + } + temp = rk[11]; + rk[12] = rk[ 4] ^ + (Te4[(temp >> 24) ] << 24) ^ + (Te4[(temp >> 16) & 0xff] << 16) ^ + (Te4[(temp >> 8) & 0xff] << 8) ^ + (Te4[(temp ) & 0xff]); + rk[13] = rk[ 5] ^ rk[12]; + rk[14] = rk[ 6] ^ rk[13]; + rk[15] = rk[ 7] ^ rk[14]; + + rk += 8; + } + } + return 0; +} + +/** + * Expand the cipher key into the decryption key schedule. + */ +int ossl_aes_set_decrypt_key(const unsigned char *userKey, const int bits, + AES_KEY *key) { + + u32 *rk; + int i, j, status; + u32 temp; + + /* first, start with an encryption schedule */ + status = ossl_aes_set_encrypt_key(userKey, bits, key); + if (status < 0) + return status; + + rk = key->rd_key; + + /* invert the order of the round keys: */ + for (i = 0, j = 4*(key->rounds); i < j; i += 4, j -= 4) { + temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp; + temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp; + temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp; + temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp; + } + /* apply the inverse MixColumn transform to all round keys but the first and the last: */ + for (i = 1; i < (key->rounds); i++) { + rk += 4; + for (j = 0; j < 4; j++) { + u32 tp1, tp2, tp4, tp8, tp9, tpb, tpd, tpe, m; + + tp1 = rk[j]; + m = tp1 & 0x80808080; + tp2 = ((tp1 & 0x7f7f7f7f) << 1) ^ + ((m - (m >> 7)) & 0x1b1b1b1b); + m = tp2 & 0x80808080; + tp4 = ((tp2 & 0x7f7f7f7f) << 1) ^ + ((m - (m >> 7)) & 0x1b1b1b1b); + m = tp4 & 0x80808080; + tp8 = ((tp4 & 0x7f7f7f7f) << 1) ^ + ((m - (m >> 7)) & 0x1b1b1b1b); + tp9 = tp8 ^ tp1; + tpb = tp9 ^ tp2; + tpd = tp9 ^ tp4; + tpe = tp8 ^ tp4 ^ tp2; +#if defined(ROTATE) + rk[j] = tpe ^ ROTATE(tpd,16) ^ + ROTATE(tp9,24) ^ ROTATE(tpb,8); +#else + rk[j] = tpe ^ (tpd >> 16) ^ (tpd << 16) ^ + (tp9 >> 8) ^ (tp9 << 24) ^ + (tpb >> 24) ^ (tpb << 8); +#endif + } + } + return 0; +} + +#endif /* AES_ASM */ + + +/* ==================================================================== +* Copyright (c) 2008 The OpenSSL Project. All rights reserved. +* +* Rights for redistribution and usage in source and binary +* forms are granted according to the OpenSSL license. +*/ +// aes modes.h & modes.c +#include +typedef void(*block128_f)(const unsigned char in[16], + unsigned char out[16], + const void *key); + +typedef void(*cbc128_f)(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], int enc); + +typedef void(*ctr128_f)(const unsigned char *in, unsigned char *out, + size_t blocks, const void *key, + const unsigned char ivec[16]); + +typedef void(*ccm128_f)(const unsigned char *in, unsigned char *out, + size_t blocks, const void *key, + const unsigned char ivec[16], unsigned char cmac[16]); + +void ossl_crypto_cbc128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], block128_f block); +void ossl_crypto_cbc128_decrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], block128_f block); + +void ossl_crypto_ctr128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], unsigned char ecount_buf[16], + unsigned int *num, block128_f block); + +void ossl_crypto_ctr128_encrypt_ctr32(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], unsigned char ecount_buf[16], + unsigned int *num, ctr128_f ctr); + +void ossl_crypto_ofb128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], int *num, + block128_f block); + +void ossl_crypto_cfb128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], int *num, + int enc, block128_f block); +void ossl_crypto_cfb128_8_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const void *key, + unsigned char ivec[16], int *num, + int enc, block128_f block); +void ossl_crypto_cfb128_1_encrypt(const unsigned char *in, unsigned char *out, + size_t bits, const void *key, + unsigned char ivec[16], int *num, + int enc, block128_f block); + +size_t ossl_crypto_cts128_encrypt_block(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], block128_f block); +size_t ossl_crypto_cts128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], cbc128_f cbc); +size_t ossl_crypto_cts128_decrypt_block(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], block128_f block); +size_t ossl_crypto_cts128_decrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], cbc128_f cbc); + +size_t ossl_crypto_nistcts128_encrypt_block(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], block128_f block); +size_t ossl_crypto_nistcts128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], cbc128_f cbc); +size_t ossl_crypto_nistcts128_decrypt_block(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], block128_f block); +size_t ossl_crypto_nistcts128_decrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], cbc128_f cbc); + +typedef struct gcm128_context GCM128_CONTEXT; + +GCM128_CONTEXT *ossl_crypto_gcm128_new(void *key, block128_f block); +void ossl_crypto_gcm128_init(GCM128_CONTEXT *ctx, void *key, block128_f block); +void ossl_crypto_gcm128_setiv(GCM128_CONTEXT *ctx, const unsigned char *iv, + size_t len); +int ossl_crypto_gcm128_aad(GCM128_CONTEXT *ctx, const unsigned char *aad, + size_t len); +int ossl_crypto_gcm128_encrypt(GCM128_CONTEXT *ctx, + const unsigned char *in, unsigned char *out, + size_t len); +int ossl_crypto_gcm128_decrypt(GCM128_CONTEXT *ctx, + const unsigned char *in, unsigned char *out, + size_t len); +int ossl_crypto_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx, + const unsigned char *in, unsigned char *out, + size_t len, ctr128_f stream); +int ossl_crypto_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx, + const unsigned char *in, unsigned char *out, + size_t len, ctr128_f stream); +int ossl_crypto_gcm128_finish(GCM128_CONTEXT *ctx, const unsigned char *tag, + size_t len); +void ossl_crypto_gcm128_tag(GCM128_CONTEXT *ctx, unsigned char *tag, size_t len); +void ossl_crypto_gcm128_release(GCM128_CONTEXT *ctx); + +typedef struct ccm128_context CCM128_CONTEXT; + +void ossl_crypto_ccm128_init(CCM128_CONTEXT *ctx, + unsigned int M, unsigned int L, void *key, block128_f block); +int ossl_crypto_ccm128_setiv(CCM128_CONTEXT *ctx, + const unsigned char *nonce, size_t nlen, size_t mlen); +void ossl_crypto_ccm128_aad(CCM128_CONTEXT *ctx, + const unsigned char *aad, size_t alen); +int ossl_crypto_ccm128_encrypt(CCM128_CONTEXT *ctx, + const unsigned char *inp, unsigned char *out, size_t len); +int ossl_crypto_ccm128_decrypt(CCM128_CONTEXT *ctx, + const unsigned char *inp, unsigned char *out, size_t len); +int ossl_crypto_ccm128_encrypt_ccm64(CCM128_CONTEXT *ctx, + const unsigned char *inp, unsigned char *out, size_t len, + ccm128_f stream); +int ossl_crypto_ccm128_decrypt_ccm64(CCM128_CONTEXT *ctx, + const unsigned char *inp, unsigned char *out, size_t len, + ccm128_f stream); +size_t ossl_crypto_ccm128_tag(CCM128_CONTEXT *ctx, unsigned char *tag, size_t len); + +typedef struct xts128_context XTS128_CONTEXT; + +int ossl_crypto_xts128_encrypt(const XTS128_CONTEXT *ctx, const unsigned char iv[16], + const unsigned char *inp, unsigned char *out, size_t len, int enc); + + +/* crypto/aes/aes_ecb.c -*- mode:C; c-file-style: "eay" -*- */ +/* ==================================================================== +* Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* +* 3. All advertising materials mentioning features or use of this +* software must display the following acknowledgment: +* "This product includes software developed by the OpenSSL Project +* for use in the OpenSSL Toolkit. (http://www.openssl.org/)" +* +* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to +* endorse or promote products derived from this software without +* prior written permission. For written permission, please contact +* openssl-core@openssl.org. +* +* 5. Products derived from this software may not be called "OpenSSL" +* nor may "OpenSSL" appear in their names without prior written +* permission of the OpenSSL Project. +* +* 6. Redistributions of any form whatsoever must retain the following +* acknowledgment: +* "This product includes software developed by the OpenSSL Project +* for use in the OpenSSL Toolkit (http://www.openssl.org/)" +* +* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY +* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR +* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +* OF THE POSSIBILITY OF SUCH DAMAGE. +* ==================================================================== +* +*/ + +#ifndef AES_DEBUG +# ifndef NDEBUG +# define NDEBUG +# endif +#endif +#include + +#include "aes.h" +//#include "aes_locl.h" + +// ECB copy from Aes_ecb.c +void osl_aes_ecb_encrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key, const int enc) +{ + + assert(in && out && key); + assert((AES_ENCRYPT == enc) || (AES_DECRYPT == enc)); + + if (AES_ENCRYPT == enc) + ossl_aes_encrypt(in, out, key); + else + ossl_aes_decrypt(in, out, key); +} + +// CBC copy from Aes_cbc.c +void ossl_aes_cbc_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const AES_KEY *key, + unsigned char *ivec, const int enc) { + + if (enc) + ossl_crypto_cbc128_encrypt(in, out, len, key, ivec, (block128_f)ossl_aes_encrypt); + else + ossl_crypto_cbc128_decrypt(in, out, len, key, ivec, (block128_f)ossl_aes_decrypt); +} + +// CFB copy from Aes_cfb.c +/* The input and output encrypted as though 128bit cfb mode is being +* used. The extra state information to record how much of the +* 128bit block we have used is contained in *num; +*/ + +void ossl_aes_cfb128_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + unsigned char *ivec, int *num, const int enc) { + + ossl_crypto_cfb128_encrypt(in, out, length, key, ivec, num, enc, (block128_f)ossl_aes_encrypt); +} + +/* N.B. This expects the input to be packed, MS bit first */ +void ossl_aes_cfb1_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + unsigned char *ivec, int *num, const int enc) +{ + ossl_crypto_cfb128_1_encrypt(in, out, length, key, ivec, num, enc, (block128_f)ossl_aes_encrypt); +} + +void ossl_aes_cfb8_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + unsigned char *ivec, int *num, const int enc) +{ + ossl_crypto_cfb128_8_encrypt(in, out, length, key, ivec, num, enc, (block128_f)ossl_aes_encrypt); +} + +// IGE copy from Aes_ige.c + +#define N_WORDS (AES_BLOCK_SIZE / sizeof(unsigned long)) +typedef struct { + unsigned long data[N_WORDS]; +} aes_block_t; + +/* XXX: probably some better way to do this */ +#if defined(__i386__) || defined(__x86_64__) +#define UNALIGNED_MEMOPS_ARE_FAST 1 +#else +#define UNALIGNED_MEMOPS_ARE_FAST 0 +#endif + +#if UNALIGNED_MEMOPS_ARE_FAST +#define load_block(d, s) (d) = *(const aes_block_t *)(s) +#define store_block(d, s) *(aes_block_t *)(d) = (s) +#else +#define load_block(d, s) memcpy((d).data, (s), AES_BLOCK_SIZE) +#define store_block(d, s) memcpy((d), (s).data, AES_BLOCK_SIZE) +#endif + +/* N.B. The IV for this mode is _twice_ the block size */ + +void ossl_aes_ige_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + unsigned char *ivec, const int enc) +{ + size_t n; + size_t len = length; + + assert(in && out && key && ivec); + assert((AES_ENCRYPT == enc) || (AES_DECRYPT == enc)); + assert((length%AES_BLOCK_SIZE) == 0); + + len = length / AES_BLOCK_SIZE; + + if (AES_ENCRYPT == enc) + { + if (in != out && + (UNALIGNED_MEMOPS_ARE_FAST || ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(long) == 0)) + { + aes_block_t *ivp = (aes_block_t *)ivec; + aes_block_t *iv2p = (aes_block_t *)(ivec + AES_BLOCK_SIZE); + + while (len) + { + aes_block_t *inp = (aes_block_t *)in; + aes_block_t *outp = (aes_block_t *)out; + + for (n = 0; n < N_WORDS; ++n) + outp->data[n] = inp->data[n] ^ ivp->data[n]; + ossl_aes_encrypt((unsigned char *)outp->data, (unsigned char *)outp->data, key); + for (n = 0; n < N_WORDS; ++n) + outp->data[n] ^= iv2p->data[n]; + ivp = outp; + iv2p = inp; + --len; + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + } + memcpy(ivec, ivp->data, AES_BLOCK_SIZE); + memcpy(ivec + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE); + } + else + { + aes_block_t tmp, tmp2; + aes_block_t iv; + aes_block_t iv2; + + load_block(iv, ivec); + load_block(iv2, ivec + AES_BLOCK_SIZE); + + while (len) + { + load_block(tmp, in); + for (n = 0; n < N_WORDS; ++n) + tmp2.data[n] = tmp.data[n] ^ iv.data[n]; + ossl_aes_encrypt((unsigned char *)tmp2.data, (unsigned char *)tmp2.data, key); + for (n = 0; n < N_WORDS; ++n) + tmp2.data[n] ^= iv2.data[n]; + store_block(out, tmp2); + iv = tmp2; + iv2 = tmp; + --len; + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + } + memcpy(ivec, iv.data, AES_BLOCK_SIZE); + memcpy(ivec + AES_BLOCK_SIZE, iv2.data, AES_BLOCK_SIZE); + } + } + else + { + if (in != out && + (UNALIGNED_MEMOPS_ARE_FAST || ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(long) == 0)) + { + aes_block_t *ivp = (aes_block_t *)ivec; + aes_block_t *iv2p = (aes_block_t *)(ivec + AES_BLOCK_SIZE); + + while (len) + { + aes_block_t tmp; + aes_block_t *inp = (aes_block_t *)in; + aes_block_t *outp = (aes_block_t *)out; + + for (n = 0; n < N_WORDS; ++n) + tmp.data[n] = inp->data[n] ^ iv2p->data[n]; + ossl_aes_decrypt((unsigned char *)tmp.data, (unsigned char *)outp->data, key); + for (n = 0; n < N_WORDS; ++n) + outp->data[n] ^= ivp->data[n]; + ivp = inp; + iv2p = outp; + --len; + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + } + memcpy(ivec, ivp->data, AES_BLOCK_SIZE); + memcpy(ivec + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE); + } + else + { + aes_block_t tmp, tmp2; + aes_block_t iv; + aes_block_t iv2; + + load_block(iv, ivec); + load_block(iv2, ivec + AES_BLOCK_SIZE); + + while (len) + { + load_block(tmp, in); + tmp2 = tmp; + for (n = 0; n < N_WORDS; ++n) + tmp.data[n] ^= iv2.data[n]; + ossl_aes_decrypt((unsigned char *)tmp.data, (unsigned char *)tmp.data, key); + for (n = 0; n < N_WORDS; ++n) + tmp.data[n] ^= iv.data[n]; + store_block(out, tmp); + iv = tmp2; + iv2 = tmp; + --len; + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + } + memcpy(ivec, iv.data, AES_BLOCK_SIZE); + memcpy(ivec + AES_BLOCK_SIZE, iv2.data, AES_BLOCK_SIZE); + } + } +} + +/* +* Note that its effectively impossible to do biIGE in anything other +* than a single pass, so no provision is made for chaining. +*/ + +/* N.B. The IV for this mode is _four times_ the block size */ + +void ossl_aes_bi_ige_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + const AES_KEY *key2, const unsigned char *ivec, + const int enc) +{ + size_t n; + size_t len = length; + unsigned char tmp[AES_BLOCK_SIZE]; + unsigned char tmp2[AES_BLOCK_SIZE]; + unsigned char tmp3[AES_BLOCK_SIZE]; + unsigned char prev[AES_BLOCK_SIZE]; + const unsigned char *iv; + const unsigned char *iv2; + + assert(in && out && key && ivec); + assert((AES_ENCRYPT == enc) || (AES_DECRYPT == enc)); + assert((length%AES_BLOCK_SIZE) == 0); + + if (AES_ENCRYPT == enc) + { + /* XXX: Do a separate case for when in != out (strictly should + check for overlap, too) */ + + /* First the forward pass */ + iv = ivec; + iv2 = ivec + AES_BLOCK_SIZE; + while (len >= AES_BLOCK_SIZE) + { + for (n = 0; n < AES_BLOCK_SIZE; ++n) + out[n] = in[n] ^ iv[n]; + ossl_aes_encrypt(out, out, key); + for (n = 0; n < AES_BLOCK_SIZE; ++n) + out[n] ^= iv2[n]; + iv = out; + memcpy(prev, in, AES_BLOCK_SIZE); + iv2 = prev; + len -= AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + } + + /* And now backwards */ + iv = ivec + AES_BLOCK_SIZE * 2; + iv2 = ivec + AES_BLOCK_SIZE * 3; + len = length; + while (len >= AES_BLOCK_SIZE) + { + out -= AES_BLOCK_SIZE; + /* XXX: reduce copies by alternating between buffers */ + memcpy(tmp, out, AES_BLOCK_SIZE); + for (n = 0; n < AES_BLOCK_SIZE; ++n) + out[n] ^= iv[n]; + /* hexdump(stdout, "out ^ iv", out, AES_BLOCK_SIZE); */ + ossl_aes_encrypt(out, out, key); + /* hexdump(stdout,"enc", out, AES_BLOCK_SIZE); */ + /* hexdump(stdout,"iv2", iv2, AES_BLOCK_SIZE); */ + for (n = 0; n < AES_BLOCK_SIZE; ++n) + out[n] ^= iv2[n]; + /* hexdump(stdout,"out", out, AES_BLOCK_SIZE); */ + iv = out; + memcpy(prev, tmp, AES_BLOCK_SIZE); + iv2 = prev; + len -= AES_BLOCK_SIZE; + } + } + else + { + /* First backwards */ + iv = ivec + AES_BLOCK_SIZE * 2; + iv2 = ivec + AES_BLOCK_SIZE * 3; + in += length; + out += length; + while (len >= AES_BLOCK_SIZE) + { + in -= AES_BLOCK_SIZE; + out -= AES_BLOCK_SIZE; + memcpy(tmp, in, AES_BLOCK_SIZE); + memcpy(tmp2, in, AES_BLOCK_SIZE); + for (n = 0; n < AES_BLOCK_SIZE; ++n) + tmp[n] ^= iv2[n]; + ossl_aes_decrypt(tmp, out, key); + for (n = 0; n < AES_BLOCK_SIZE; ++n) + out[n] ^= iv[n]; + memcpy(tmp3, tmp2, AES_BLOCK_SIZE); + iv = tmp3; + iv2 = out; + len -= AES_BLOCK_SIZE; + } + + /* And now forwards */ + iv = ivec; + iv2 = ivec + AES_BLOCK_SIZE; + len = length; + while (len >= AES_BLOCK_SIZE) + { + memcpy(tmp, out, AES_BLOCK_SIZE); + memcpy(tmp2, out, AES_BLOCK_SIZE); + for (n = 0; n < AES_BLOCK_SIZE; ++n) + tmp[n] ^= iv2[n]; + ossl_aes_decrypt(tmp, out, key); + for (n = 0; n < AES_BLOCK_SIZE; ++n) + out[n] ^= iv[n]; + memcpy(tmp3, tmp2, AES_BLOCK_SIZE); + iv = tmp3; + iv2 = out; + len -= AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + } + } +} + + +////////////////////////////// implementions /////////////////////////// +/// copy from cbc128.c +#ifndef MODES_DEBUG +# ifndef NDEBUG +# define NDEBUG +# endif +#endif +#include + +// define STRICT_ALIGNMENT 1 + +#ifndef STRICT_ALIGNMENT +# define STRICT_ALIGNMENT 0 +#endif + +void ossl_crypto_cbc128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], block128_f block) +{ + size_t n; + const unsigned char *iv = ivec; + + assert(in && out && key && ivec); + +#if !defined(OPENSSL_SMALL_FOOTPRINT) + if (STRICT_ALIGNMENT && + ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) { + while (len >= 16) { + for (n = 0; n<16; ++n) + out[n] = in[n] ^ iv[n]; + (*block)(out, out, key); + iv = out; + len -= 16; + in += 16; + out += 16; + } + } + else { + while (len >= 16) { + for (n = 0; n<16; n += sizeof(size_t)) + *(size_t*)(out + n) = + *(size_t*)(in + n) ^ *(size_t*)(iv + n); + (*block)(out, out, key); + iv = out; + len -= 16; + in += 16; + out += 16; + } + } +#endif + while (len) { + for (n = 0; n<16 && n= 16) { + (*block)(in, out, key); + for (n = 0; n<16; ++n) + out[n] ^= iv[n]; + iv = in; + len -= 16; + in += 16; + out += 16; + } + } + else { + while (len >= 16) { + (*block)(in, out, key); + for (n = 0; n<16; n += sizeof(size_t)) + *(size_t *)(out + n) ^= *(size_t *)(iv + n); + iv = in; + len -= 16; + in += 16; + out += 16; + } + } + memcpy(ivec, iv, 16); + } + else { + if (STRICT_ALIGNMENT && + ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) { + unsigned char c; + while (len >= 16) { + (*block)(in, tmp.c, key); + for (n = 0; n<16; ++n) { + c = in[n]; + out[n] = tmp.c[n] ^ ivec[n]; + ivec[n] = c; + } + len -= 16; + in += 16; + out += 16; + } + } + else { + size_t c; + while (len >= 16) { + (*block)(in, tmp.c, key); + for (n = 0; n<16; n += sizeof(size_t)) { + c = *(size_t *)(in + n); + *(size_t *)(out + n) = + *(size_t *)(tmp.c + n) ^ *(size_t *)(ivec + n); + *(size_t *)(ivec + n) = c; + } + len -= 16; + in += 16; + out += 16; + } + } + } +#endif + while (len) { + unsigned char c; + (*block)(in, tmp.c, key); + for (n = 0; n<16 && n + +/* The input and output encrypted as though 128bit cfb mode is being +* used. The extra state information to record how much of the +* 128bit block we have used is contained in *num; +*/ +void ossl_crypto_cfb128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], int *num, + int enc, block128_f block) +{ + unsigned int n; + size_t l = 0; + + assert(in && out && key && ivec && num); + + n = *num; + + if (enc) { +#if !defined(OPENSSL_SMALL_FOOTPRINT) + if (16 % sizeof(size_t) == 0) do { /* always true actually */ + while (n && len) { + *(out++) = ivec[n] ^= *(in++); + --len; + n = (n + 1) % 16; + } +#if defined(STRICT_ALIGNMENT) + if (((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) + break; +#endif + while (len >= 16) { + (*block)(ivec, ivec, key); + for (; n<16; n += sizeof(size_t)) { + *(size_t*)(out + n) = + *(size_t*)(ivec + n) ^= *(size_t*)(in + n); + } + len -= 16; + out += 16; + in += 16; + n = 0; + } + if (len) { + (*block)(ivec, ivec, key); + while (len--) { + out[n] = ivec[n] ^= in[n]; + ++n; + } + } + *num = n; + return; + } while (0); + /* the rest would be commonly eliminated by x86* compiler */ +#endif + while (l= 16) { + (*block)(ivec, ivec, key); + for (; n<16; n += sizeof(size_t)) { + size_t t = *(size_t*)(in + n); + *(size_t*)(out + n) = *(size_t*)(ivec + n) ^ t; + *(size_t*)(ivec + n) = t; + } + len -= 16; + out += 16; + in += 16; + n = 0; + } + if (len) { + (*block)(ivec, ivec, key); + while (len--) { + unsigned char c; + out[n] = ivec[n] ^ (c = in[n]); ivec[n] = c; + ++n; + } + } + *num = n; + return; + } while (0); + /* the rest would be commonly eliminated by x86* compiler */ +#endif + while (l128) return; + + /* fill in the first half of the new IV with the current IV */ + memcpy(ovec, ivec, 16); + /* construct the new IV */ + (*block)(ivec, ivec, key); + num = (nbits + 7) / 8; + if (enc) /* encrypt the input */ + for (n = 0; n < num; ++n) + out[n] = (ovec[16 + n] = in[n] ^ ivec[n]); + else /* decrypt the input */ + for (n = 0; n < num; ++n) + out[n] = (ovec[16 + n] = in[n]) ^ ivec[n]; + /* shift ovec left... */ + rem = nbits % 8; + num = nbits / 8; + if (rem == 0) + memcpy(ivec, ovec + num, 16); + else + for (n = 0; n < 16; ++n) + ivec[n] = ovec[n + num] << rem | ovec[n + num + 1] >> (8 - rem); + + /* it is not necessary to cleanse ovec, since the IV is not secret */ +} + +/* N.B. This expects the input to be packed, MS bit first */ +void ossl_crypto_cfb128_1_encrypt(const unsigned char *in, unsigned char *out, + size_t bits, const void *key, + unsigned char ivec[16], int *num, + int enc, block128_f block) +{ + size_t n; + unsigned char c[1], d[1]; + + assert(in && out && key && ivec && num); + assert(*num == 0); + + for (n = 0; n> (unsigned int)(n % 8)); + } +} + +void ossl_crypto_cfb128_8_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const void *key, + unsigned char ivec[16], int *num, + int enc, block128_f block) +{ + size_t n; + + assert(in && out && key && ivec && num); + assert(*num == 0); + + for (n = 0; n= 16) { + (*block)(ivec, ecount_buf, key); + ctr128_inc_aligned(ivec); + for (; n<16; n += sizeof(size_t)) + *(size_t *)(out + n) = + *(size_t *)(in + n) ^ *(size_t *)(ecount_buf + n); + len -= 16; + out += 16; + in += 16; + n = 0; + } + if (len) { + (*block)(ivec, ecount_buf, key); + ctr128_inc_aligned(ivec); + while (len--) { + out[n] = in[n] ^ ecount_buf[n]; + ++n; + } + } + *num = n; + return; + } while (0); + /* the rest would be commonly eliminated by x86* compiler */ +#endif + while (l= 16) { + size_t blocks = len / 16; + /* + * 1<<28 is just a not-so-small yet not-so-large number... + * Below condition is practically never met, but it has to + * be checked for code correctness. + */ + if (sizeof(size_t)>sizeof(unsigned int) && blocks>(1U << 28)) + blocks = (1U << 28); + /* + * As (*func) operates on 32-bit counter, caller + * has to handle overflow. 'if' below detects the + * overflow, which is then handled by limiting the + * amount of blocks to the exact overflow point... + */ + ctr32 += (u32)blocks; + if (ctr32 < blocks) { + blocks -= ctr32; + ctr32 = 0; + } + (*func)(in, out, blocks, key, ivec); + /* (*ctr) does not update ivec, caller does: */ + PUTU32(ivec + 12, ctr32); + /* ... overflow was detected, propogate carry. */ + if (ctr32 == 0) ctr96_inc(ivec); + blocks *= 16; + len -= blocks; + out += blocks; + in += blocks; + } + if (len) { + memset(ecount_buf, 0, 16); + (*func)(ecount_buf, ecount_buf, 1, key, ivec); + ++ctr32; + PUTU32(ivec + 12, ctr32); + if (ctr32 == 0) ctr96_inc(ivec); + while (len--) { + out[n] = in[n] ^ ecount_buf[n]; + ++n; + } + } + + *num = n; +} + +void ossl_aes_ctr128_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + unsigned char ivec[AES_BLOCK_SIZE], + unsigned char ecount_buf[AES_BLOCK_SIZE], + unsigned int *num) +{ + ossl_crypto_ctr128_encrypt(in, out, length, key, ivec, ecount_buf, num, (block128_f)ossl_aes_encrypt); +} + +////////////////////////////////////////////////////////////////////////////////// +//////////////////// copy from openssl/crypto/modes/ofb128.c ///////////////////// +/* The input and output encrypted as though 128bit ofb mode is being +* used. The extra state information to record how much of the +* 128bit block we have used is contained in *num; +*/ +void ossl_crypto_ofb128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], int *num, + block128_f block) +{ + unsigned int n; + size_t l = 0; + + assert(in && out && key && ivec && num); + + n = *num; + +#if !defined(OPENSSL_SMALL_FOOTPRINT) + if (16 % sizeof(size_t) == 0) do { /* always true actually */ + while (n && len) { + *(out++) = *(in++) ^ ivec[n]; + --len; + n = (n + 1) % 16; + } +#if defined(STRICT_ALIGNMENT) + if (((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) + break; +#endif + while (len >= 16) { + (*block)(ivec, ivec, key); + for (; n<16; n += sizeof(size_t)) + *(size_t*)(out + n) = + *(size_t*)(in + n) ^ *(size_t*)(ivec + n); + len -= 16; + out += 16; + in += 16; + n = 0; + } + if (len) { + (*block)(ivec, ivec, key); + while (len--) { + out[n] = in[n] ^ ivec[n]; + ++n; + } + } + *num = n; + return; + } while (0); + /* the rest would be commonly eliminated by x86* compiler */ +#endif + while (lgetScheduler()->performFunctionInCocosThread([=]{cocos2d::log((format), ##__VA_ARGS__);}) +#else +#if defined(_WIN32) +static void odprintf(const char* format, ...) { + va_list args; + va_start(args, format); + int len = _vscprintf(format, args); + if (len > 0) { + len += (1 + 2); + char* buf = (char*)malloc(len); + if (buf) { + len = vsprintf_s(buf, len, format, args); + if (len > 0) { + while (len && isspace(buf[len - 1])) len--; + buf[len++] = '\r'; + buf[len++] = '\n'; + buf[len] = 0; + OutputDebugStringA(buf); + } + free(buf); + } + va_end(args); + } +} +#define INET_LOG(format,...) odprintf((format "\r\n"),##__VA_ARGS__) // fprintf(stdout,(format "\n"),##__VA_ARGS__) +#else +#define INET_LOG(format,...) fprintf(stdout,(format "\n"),##__VA_ARGS__) +#endif +#endif + + +#ifdef _WIN32 +#if !defined(WINRT) +#include +#pragma comment(lib, "winmm.lib") +#endif +#endif + +#define MAX_WAIT_DURATION 5 * 60 * 1000 * 1000 // 5 minites + +#define MAX_BUSY_DELAY 1000 // 1 millisecond + +#define MAX_PDU_LEN SZ(10, M) + +#define TSF_CALL(stmt) this->call_tsf_([=]{(stmt);}); + +namespace purelib { +namespace inet { +class appl_pdu +{ +public: + appl_pdu(std::vector&& right, const appl_pdu_send_callback_t& callback, const std::chrono::microseconds& duration) + { + data_ = std::move(right); + offset_ = 0; + on_sent_ = callback; + expire_time_ = std::chrono::steady_clock::now() + duration; + } + bool expired() const { + return (expire_time_ - std::chrono::steady_clock::now()).count() < 0; + } + std::vector data_; // sending data + size_t offset_; // offset + appl_pdu_send_callback_t on_sent_; + compatible_timepoint_t expire_time_; + + static void * operator new(size_t /*size*/) + { + return get_pool().get(); + } + + static void operator delete(void *p) + { + get_pool().release(p); + } + + static purelib::gc::object_pool& get_pool() + { + static purelib::gc::object_pool s_pool; + return s_pool; + } +}; + +void p2p_io_ctx::reset() +{ + connected_ = false; + receiving_pdu_.clear(); + offset_ = 0; + expected_pdu_length_ = -1; + error = 0; + + if (this->impl_.is_open()) { + this->impl_.close(); + } +} + +async_tcp_client::async_tcp_client() : app_exiting_(false), + thread_started_(false), + interrupter_(), + address_("192.168.1.104"), + port_(8001), + connect_timeout_(3), + send_timeout_(3), + decode_pdu_length_(nullptr), + error_number_(error_number::ERR_OK), + idle_(true), + connect_failed_(false), + connect_wait_timeout_(-1) +{ + FD_ZERO(&fds_array_[read_op]); + FD_ZERO(&fds_array_[write_op]); + FD_ZERO(&fds_array_[read_op]); + + maxfdp_ = 0; + reset(); +} + +async_tcp_client::~async_tcp_client() +{ + app_exiting_ = true; + + // shutdown_p2p_chancel(); + this->p2p_acceptor_.close(); + + close(); + + this->connect_notify_cv_.notify_all(); + + if (this->worker_thread_.joinable()) + this->worker_thread_.join(); +} + +void async_tcp_client::set_timeouts(long timeo_connect, long timeo_send) +{ + this->connect_timeout_ = timeo_connect; + this->send_timeout_ = timeo_send; +} + +void async_tcp_client::set_endpoint(const char* address, const char* addressv6, u_short port) +{ + this->address_ = address; + this->addressv6_ = address; + this->port_ = port; +} + +void async_tcp_client::set_callbacks( + decode_pdu_length_func decode_length_func, + const connection_lost_callback_t& on_connection_lost, + const appl_pdu_recv_callback_t& callback, + const std::function& threadsafe_call) +{ + this->decode_pdu_length_ = decode_length_func; + this->on_received_pdu_ = callback; + this->on_connection_lost_ = on_connection_lost; + this->call_tsf_ = threadsafe_call; +} + +size_t async_tcp_client::get_received_pdu_count(void) const +{ + return recv_queue_.size(); +} + +void async_tcp_client::dispatch_received_pdu(int count) { + assert(this->on_received_pdu_ != nullptr); + + if (this->recv_queue_.empty()) + return; + + std::lock_guard autolock(this->recv_queue_mtx_); + do { + auto packet = std::move(this->recv_queue_.front()); + this->recv_queue_.pop_front(); + this->on_received_pdu_(std::move(packet)); + } while (!this->recv_queue_.empty() && --count > 0); +} + +void async_tcp_client::start_service(int /*working_counter*/) +{ + if (!thread_started_) { + thread_started_ = true; + worker_thread_ = std::thread([this] { + INET_LOG("async_tcp_client thread running..."); + this->service(); + INET_LOG("async_tcp_client thread exited."); + }); + } +} + +void async_tcp_client::set_connect_listener(const connect_listener& listener) +{ + this->connect_listener_ = listener; +} + +void async_tcp_client::set_connect_wait_timeout(long seconds/*-1: disable auto connect */) +{ + this->connect_wait_timeout_ = seconds; +} + +void async_tcp_client::wait_connect_notify() +{ + std::unique_lock autolock(connect_notify_mtx_); + if (connect_wait_timeout_ == -1) + connect_notify_cv_.wait(autolock); + else + connect_notify_cv_.wait_for(autolock, std::chrono::seconds(connect_wait_timeout_)); +} + +void async_tcp_client::service() +{ +#if defined(_WIN32) && !defined(WINRT) + timeBeginPeriod(1); +#endif + + if (this->suspended_) + return; + + while (!app_exiting_) + { + bool connection_ok = impl_.is_open(); + + if (!connection_ok) + { // if no connect, wait connect notify. + if (total_connect_times_ >= 0) + wait_connect_notify(); + ++total_connect_times_; + connection_ok = this->connect(); + if (!connection_ok) { /// connect failed, waiting connect notify + // reconnClock = clock(); never use clock api on android platform + continue; + } + } + + + // event loop + fd_set fds_array[3]; + timeval timeout; + + for (; !app_exiting_;) + { + ::memcpy(&fds_array, this->fds_array_, sizeof(this->fds_array_)); + + // @pitfall: If still have data to read, only wait 1 millseconds. + get_wait_duration(timeout, this->offset_ > 0 ? MAX_BUSY_DELAY : MAX_WAIT_DURATION); +#if INET_ENABLE_VERBOSE_LOG + INET_LOG("socket.select maxfdp:%d waiting... %ld milliseconds", maxfdp_, timeout.tv_sec * 1000 + timeout.tv_usec / 1000); +#endif + int nfds = ::select(maxfdp_, &(fds_array[read_op]), nullptr, nullptr, &timeout); +#if INET_ENABLE_VERBOSE_LOG + INET_LOG("socket.select waked up, retval=%d", nfds); +#endif + if (nfds == -1) + { + int ec = xxsocket::get_last_errno(); + INET_LOG("socket.select failed, error code: %d, error msg:%s\n", ec, xxsocket::get_error_msg(ec)); + if (ec == EBADF || !this->impl_.is_open()) { + goto _L_error; + } + continue; // try select again. + } + + if (nfds == 0) { +#if INET_ENABLE_VERBOSE_LOG + INET_LOG("socket.select is timeout, do perform_timeout_timers()"); +#endif + } + // Reset the interrupter. + else if (nfds > 0 && FD_ISSET(this->interrupter_.read_descriptor(), &(fds_array[read_op]))) + { + bool was_interrupt = interrupter_.reset(); +#if INET_ENABLE_VERBOSE_LOG + INET_LOG("socket.select waked up by interrupt, interrupter fd:%d, was_interrupt:%s", this->interrupter_.read_descriptor(), was_interrupt ? "true" : "false"); +#endif + --nfds; + } + +#if 0 + // we should check whether the connection have exception before any operations. + if (FD_ISSET(this->impl_.native_handle(), &(fds_array[except_op]))) + { + int ec = xxsocket::get_last_errno(); + INET_LOG("socket.select exception triggered, error code: %d, error msg:%s\n", ec, xxsocket::get_error_msg(ec)); + goto _L_error; + } +#endif + if (nfds > 0 || this->offset_ > 0) { +#if INET_ENABLE_VERBOSE_LOG + INET_LOG("perform read operation..."); +#endif + if (!do_read(this)) { + // INET_LOG("do read failed..."); + goto _L_error; + } + } + + send_queue_mtx_.lock(); + // perform write operations + if (!this->send_queue_.empty()) { +#if INET_ENABLE_VERBOSE_LOG + INET_LOG("perform write operation..."); +#endif + if (!do_write(this)) + { // TODO: check would block? for client, may be unnecessary. + send_queue_mtx_.unlock(); + goto _L_error; + } + } + send_queue_mtx_.unlock(); + + perform_timeout_timers(); + } + + continue; + + _L_error: + handle_error(); + } + +#if defined(_WIN32) && !defined(WINRT) + timeEndPeriod(1); +#endif +} + +void async_tcp_client::close() +{ + if (impl_.is_open()) { + impl_.shutdown(); + impl_.close(); + } + + interrupter_.interrupt(); +} + +void async_tcp_client::notify_connect() +{ + std::unique_lock autolock(connect_notify_mtx_); + connect_notify_cv_.notify_one(); +} + +void async_tcp_client::switch_endpoint(const char* address, u_short port) +{ + this->address_ = address; + this->port_ = port; + this->switching_ = true; + close(); +} + +void async_tcp_client::handle_error(void) +{ + if (impl_.is_open()) { + impl_.close(); + } + else { + INET_LOG("local close the connection!"); + } + + connected_ = false; + + // @Notify connection lost + if (this->on_connection_lost_) { + int ec = error_number_; + TSF_CALL(on_connection_lost_(!this->switching_ ? ec : -200, xxsocket::get_error_msg(ec))); + } + + // @Clear all sending messages + this->send_queue_mtx_.lock(); + if (!send_queue_.empty()) { + for (auto pdu : send_queue_) + delete pdu; + send_queue_.clear(); + } + this->send_queue_mtx_.unlock(); + + // @Notify all timers are cancelled. + this->timer_queue_mtx_.lock(); + //for (auto& timer : timer_queue_) + // timer->callback_(true); + this->timer_queue_.clear(); + this->timer_queue_mtx_.unlock(); + + interrupter_.reset(); +} + +void async_tcp_client::register_descriptor(const socket_native_type fd, int flags) +{ + if ((flags & socket_event_read) != 0) + { + FD_SET(fd, &(fds_array_[read_op])); + } + + if ((flags & socket_event_write) != 0) + { + FD_SET(fd, &(fds_array_[write_op])); + } + + if ((flags & socket_event_except) != 0) + { + FD_SET(fd, &(fds_array_[except_op])); + } + + if (maxfdp_ < static_cast(fd) + 1) + maxfdp_ = static_cast(fd) + 1; +} + +void async_tcp_client::unregister_descriptor(const socket_native_type fd, int flags) +{ + if ((flags & socket_event_read) != 0) + { + FD_CLR(fd, &(fds_array_[read_op])); + } + + if ((flags & socket_event_write) != 0) + { + FD_CLR(fd, &(fds_array_[write_op])); + } + + if ((flags & socket_event_except) != 0) + { + FD_CLR(fd, &(fds_array_[except_op])); + } +} + +void async_tcp_client::async_send(std::vector&& data, const appl_pdu_send_callback_t& callback) +{ + if (this->impl_.is_open()) + { + auto pdu = new appl_pdu(std::move(data), callback, std::chrono::seconds(this->send_timeout_)); + + send_queue_mtx_.lock(); + send_queue_.push_back(pdu); + send_queue_mtx_.unlock(); + + interrupter_.interrupt(); + } + else { + INET_LOG("async_tcp_client::send failed, The connection not ok!!!"); + } +} + +void async_tcp_client::move_received_pdu(p2p_io_ctx* ctx) +{ +#if INET_ENABLE_VERBOSE_LOG + INET_LOG("move_received_pdu..."); +#endif + recv_queue_mtx_.lock(); + recv_queue_.push_back(std::move(ctx->receiving_pdu_)); // without data copy + recv_queue_mtx_.unlock(); + + ctx->expected_pdu_length_ = -1; +} + + +bool async_tcp_client::connect(void) +{ + if (connect_failed_) + { + connect_failed_ = false; + } + + INET_LOG("connecting server %s:%u...", address_.c_str(), port_); + + int ret = -1; + this->connected_ = false; + int flags = xxsocket::getipsv(); + if (flags & ipsv_ipv4) { + ret = impl_.pconnect_n(this->address_.c_str(), this->port_, this->connect_timeout_); + } + else if (flags & ipsv_ipv6) + { // client is IPV6_Only + INET_LOG("Client needs a ipv6 server address to connect!"); + ret = impl_.pconnect_n(this->addressv6_.c_str(), this->port_, this->connect_timeout_); + } + if (ret == 0) + { // connect succeed, reset fds + FD_ZERO(&fds_array_[read_op]); + FD_ZERO(&fds_array_[write_op]); + FD_ZERO(&fds_array_[except_op]); + + register_descriptor(interrupter_.read_descriptor(), socket_event_read); + register_descriptor(impl_.native_handle(), socket_event_read); + + impl_.set_nonblocking(true); + + expected_pdu_length_ = -1; + error_number_ = error_number::ERR_OK; + offset_ = 0; + receiving_pdu_.clear(); + recv_queue_.clear(); + + this->impl_.set_optval(SOL_SOCKET, SO_REUSEADDR, 1); // set opt for p2p + + INET_LOG("connect server: %s:%u succeed, fd=%d interrupter_fd=%d", address_.c_str(), port_, impl_.native_handle(), interrupter_.read_descriptor()); + +#if 0 // provided as API + auto endp = this->impl_.local_endpoint(); + // INETLOG("local endpoint: %s", endp.to_string().c_str()); + + if (p2p_acceptor_.reopen()) + { // start p2p listener + if (p2p_acceptor_.bind(endp) == 0) + { + if (p2p_acceptor_.listen() == 0) + { + // set socket to async + p2p_acceptor_.set_nonblocking(true); + + // register p2p's peer connect event + register_descriptor(p2p_acceptor_, socket_event_read); + // INETLOG("listening at local %s successfully.", endp.to_string().c_str()); + } + } + } +#endif + + this->connected_ = true; + if (this->connect_listener_ != nullptr) { + auto switching = this->switching_; + TSF_CALL(this->connect_listener_(true, !switching ? 0 : -200)); + } + + this->switching_ = false; + + return true; + } + else { // connect server failed. + connect_failed_ = true; + int ec = xxsocket::get_last_errno(); + if (this->connect_listener_ != nullptr) { + TSF_CALL(this->connect_listener_(false, !this->switching_ ? ec : -200)); + } + + INET_LOG("connect server: %s:%u failed, error code:%d, error msg:%s!", address_.c_str(), port_, ec, xxsocket::get_error_msg(ec)); + + this->switching_ = false; + + return false; + } +} + +bool async_tcp_client::do_write(p2p_io_ctx* ctx) +{ + bool bRet = false; + + do { + int n; + + if (!ctx->impl_.is_open()) + break; + + if (!ctx->send_queue_.empty()) { + auto& v = ctx->send_queue_.front(); + auto bytes_left = v->data_.size() - v->offset_; + n = ctx->impl_.send_i(v->data_.data() + v->offset_, bytes_left); + if (n == bytes_left) { // All pdu bytes sent. + ctx->send_queue_.pop_front(); + this->call_tsf_([v] { +#if INET_ENABLE_VERBOSE_LOG + auto packetSize = v->data_.size(); + INET_LOG("async_tcp_client::do_write ---> A packet sent success, packet size:%d", packetSize); +#endif + if (v->on_sent_ != nullptr) + v->on_sent_(error_number::ERR_OK); + delete v; + }); + } + else if (n > 0) { // TODO: add time + if (!v->expired()) + { // change offset, remain data will send next time. + // v->data_.erase(v->data_.begin(), v->data_.begin() + n); + v->offset_ += n; + int temp_left = v->data_.size() - v->offset_; + int timestamp = time(NULL); + INET_LOG("=======> [%d]send not complete %d bytes remained, %dbytes was sent!", timestamp, temp_left, n); + } + else { // send timeout + ctx->send_queue_.pop_front(); + this->call_tsf_([v] { + + auto packetSize = v->data_.size(); + INET_LOG("async_tcp_client::do_write ---> A packet sent timeout, packet size:%d", packetSize); + + if (v->on_sent_) + v->on_sent_(error_number::ERR_SEND_TIMEOUT); + delete v; + }); + } + } + else { // n <= 0, TODO: add time + error_number_ = xxsocket::get_last_errno(); + if (SHOULD_CLOSE_1(n, error_number_)) { + ctx->send_queue_.pop_front(); + + int ec = error_number_; + std::string errormsg = xxsocket::get_error_msg(ec); + + int timestamp = time(NULL); + INET_LOG("[%d]async_tcp_client::do_write failed, the connection should be closed, retval=%d, socket error:%d, detail:%s", timestamp, n, ec, errormsg.c_str()); + + this->call_tsf_([v] { + if (v->on_sent_) + v->on_sent_(error_number::ERR_CONNECTION_LOST); + delete v; + }); + + break; + } + } + idle_ = false; + } + + bRet = true; + } while (false); + + return bRet; +} + +bool async_tcp_client::do_read(p2p_io_ctx* ctx) +{ + bool bRet = false; + do { + if (!ctx->impl_.is_open()) + break; + + int n = ctx->impl_.recv_i(ctx->buffer_ + ctx->offset_, sizeof(ctx->buffer_) - ctx->offset_); + + if (n > 0 || (n == -1 && ctx->offset_ != 0)) { + + if (n == -1) + n = 0; +#if INET_ENABLE_VERBOSE_LOG + INET_LOG("async_tcp_client::do_read --- received data len: %d, buffer data len: %d", n, n + ctx->offset_); +#endif + if (ctx->expected_pdu_length_ == -1) { // decode length + if (decode_pdu_length_(ctx->buffer_, ctx->offset_ + n, ctx->expected_pdu_length_)) + { + if (ctx->expected_pdu_length_ < 0) { // header insuff + ctx->offset_ += n; + } + else { // ok + ctx->receiving_pdu_.reserve(ctx->expected_pdu_length_); // #perfomance, avoid memory reallocte. + + auto bytes_transferred = n + ctx->offset_; + ctx->receiving_pdu_.insert(ctx->receiving_pdu_.end(), ctx->buffer_, ctx->buffer_ + (std::min)(ctx->expected_pdu_length_, bytes_transferred)); + if (bytes_transferred >= ctx->expected_pdu_length_) + { // pdu received properly + ctx->offset_ = bytes_transferred - ctx->expected_pdu_length_; // set offset to bytes of remain buffer + if (ctx->offset_ > 0) // move remain data to head of buffer and hold offset. + ::memmove(ctx->buffer_, ctx->buffer_ + ctx->expected_pdu_length_, offset_); + + // move properly pdu to ready queue, GL thread will retrieve it. + move_received_pdu(ctx); + } + else { // all buffer consumed, set offset to ZERO, pdu incomplete, continue recv remain data. + ctx->offset_ = 0; + } + } + } + else { + error_number_ = error_number::ERR_DPL_ILLEGAL_PDU; + int timestamp = time(NULL); + INET_LOG("[%d]async_tcp_client::do_read error, decode length of pdu failed!", timestamp); + break; + } + } + else { // recv remain pdu data + auto bytes_transferred = n + ctx->offset_;// bytes transferred at this time + if ((ctx->receiving_pdu_.size() + bytes_transferred) > MAX_PDU_LEN) // TODO: config MAX_PDU_LEN, now is 16384 + { + error_number_ = error_number::ERR_PDU_TOO_LONG; + int timestamp = time(NULL); + INET_LOG("[%d]async_tcp_client::do_read error, The length of pdu too long!", timestamp); + break; + } + else { + auto bytes_needed = ctx->expected_pdu_length_ - static_cast(ctx->receiving_pdu_.size()); // never equal zero or less than zero + if (bytes_needed > 0) { + ctx->receiving_pdu_.insert(ctx->receiving_pdu_.end(), ctx->buffer_, ctx->buffer_ + (std::min)(bytes_transferred, bytes_needed)); + + ctx->offset_ = bytes_transferred - bytes_needed; // set offset to bytes of remain buffer + if (ctx->offset_ >= 0) + { // pdu received properly + if (ctx->offset_ > 0) // move remain data to head of buffer and hold offset. + ::memmove(ctx->buffer_, ctx->buffer_ + bytes_needed, ctx->offset_); + + // move properly pdu to ready queue, GL thread will retrieve it. + move_received_pdu(ctx); + } + else { // all buffer consumed, set offset to ZERO, pdu incomplete, continue recv remain data. + ctx->offset_ = 0; + } + } + else { + //assert(false); + } + } + } + + this->idle_ = false; + } + else { + error_number_ = xxsocket::get_last_errno(); + if (SHOULD_CLOSE_0(n, error_number_)) { + int ec = error_number_; + std::string errormsg = xxsocket::get_error_msg(ec); + int timestamp = time(NULL); + if (n == 0) { + INET_LOG("[%d]async_tcp_client::do_read error, the server close the connection, retval=%d, socket error:%d, detail:%s", timestamp, n, ec, errormsg.c_str()); + } + else { + INET_LOG("[%d]async_tcp_client::do_read error, the connection should be closed, retval=%d, socket error:%d, detail:%s", timestamp, n, ec, errormsg.c_str()); + } + break; + } + } + + bRet = true; + + } while (false); + + return bRet; +} + +void async_tcp_client::schedule_timer(deadline_timer* timer) +{ + std::lock_guard lk(this->timer_queue_mtx_); + if (std::find(timer_queue_.begin(), timer_queue_.end(), timer) != timer_queue_.end()) + return; + + this->timer_queue_.push_back(timer); + + std::sort(this->timer_queue_.begin(), this->timer_queue_.end(), [](deadline_timer* lhs, deadline_timer* rhs) { + return lhs->wait_duration() > rhs->wait_duration(); + }); + + if (timer == *this->timer_queue_.begin()) + interrupter_.interrupt(); +} + +void async_tcp_client::cancel_timer(deadline_timer* timer) +{ + std::lock_guard lk(this->timer_queue_mtx_); + + auto iter = std::find(timer_queue_.begin(), timer_queue_.end(), timer); + if (iter != timer_queue_.end()) { + timer->callback_(true); + timer_queue_.erase(iter); + } +} + +void async_tcp_client::perform_timeout_timers() +{ + if (timer_queue_.empty()) + return; + + std::lock_guard lk(this->timer_queue_mtx_); + + std::vector loop_timers; + while (!this->timer_queue_.empty()) + { + auto earliest = timer_queue_.back(); + if (earliest->expired()) + { + timer_queue_.pop_back(); + TSF_CALL(earliest->callback_(false)); + if (earliest->loop_) { + earliest->expires_from_now(); + loop_timers.push_back(earliest); + } + } + else { + break; + } + } + + if (!loop_timers.empty()) { + this->timer_queue_.insert(this->timer_queue_.end(), loop_timers.begin(), loop_timers.end()); + std::sort(this->timer_queue_.begin(), this->timer_queue_.end(), [](deadline_timer* lhs, deadline_timer* rhs) { + return lhs->wait_duration() > rhs->wait_duration(); + }); + } +} + +void async_tcp_client::get_wait_duration(timeval& tv, long long usec) +{ + // If send_queue_ not empty, we should perform it immediately. + // so set socket.select timeout to ZERO. + this->send_queue_mtx_.lock(); + if (!this->send_queue_.empty()) + { + this->send_queue_mtx_.unlock(); + ::memset(&tv, 0x0, sizeof(tv)); + return; + } + this->send_queue_mtx_.unlock(); + + this->timer_queue_mtx_.lock(); + auto earliest = !this->timer_queue_.empty() ? timer_queue_.back() : nullptr; + this->timer_queue_mtx_.unlock(); + + std::chrono::microseconds min_duration(usec); // microseconds + if (earliest != nullptr) { + auto duration = earliest->wait_duration(); + if (min_duration > duration) + min_duration = duration; + } + + usec = min_duration.count(); + + if (usec > 0) { + tv.tv_sec = usec / 1000000; + tv.tv_usec = usec % 1000000; + } + else { + ::memset(&tv, 0x0, sizeof(tv)); + } +} + +void async_tcp_client::p2p_open() +{ + if (is_connected()) { + if (this->p2p_acceptor_.reopen()) + { + this->p2p_acceptor_.bind(this->impl_.local_endpoint()); + this->p2p_acceptor_.listen(1); // We just listen one connection for p2p + register_descriptor(this->p2p_acceptor_, socket_event_read); + } + } +} + +bool async_tcp_client::p2p_do_accept(void) +{ + if (this->p2p_channel2_.impl_.is_open()) + { // Just ignore other connect request for 1 <<-->> 1 connections. + this->p2p_acceptor_.accept().close(); + return true; + } + + this->idle_ = false; + this->p2p_channel2_.impl_ = this->p2p_acceptor_.accept(); + return this->p2p_channel2_.impl_.is_open(); +} + +} /* namespace purelib::net */ +} /* namespace purelib */ diff --git a/src/xxtcp_client.h b/src/async_tcp_client.h similarity index 45% rename from src/xxtcp_client.h rename to src/async_tcp_client.h index 2eb54acde12ba268c2cecc708cab716fb5446237..111470ec378ffa39641a3d99f026f88336048f46 100644 --- a/src/xxtcp_client.h +++ b/src/async_tcp_client.h @@ -1,5 +1,33 @@ -#ifndef _XXTCP_CLIENT_H_ -#define _XXTCP_CLIENT_H_ +////////////////////////////////////////////////////////////////////////////////////////// +// A cross platform socket APIs, support ios & android & wp8 & window store universal app +// version: 2.3 +////////////////////////////////////////////////////////////////////////////////////////// +/* +The MIT License (MIT) + +Copyright (c) 2012-2016 halx99 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#ifndef _ASYNC_TCP_CLIENT_H_ +#define _ASYNC_TCP_CLIENT_H_ #include "xxsocket.h" #include "endian_portable.h" #include "singleton.h" @@ -10,19 +38,24 @@ #include #include #include +#include +#include +#include "object_pool.h" +#include "select_interrupter.hpp" +#include "deadline_timer.h" namespace purelib { namespace inet { - enum P2PChannelType { + enum { TCP_P2P_UNKNOWN = -1, TCP_P2P_CLIENT = 1, // local --> peer TCP_P2P_SERVER, // peer --> local }; - enum ErrorCode { + enum error_number { ERR_OK, // NO ERROR - ERR_CONNECT_FAILED, // connect failed + ERR_CONNECT_FAILED = -201, // connect failed ERR_CONNECT_TIMEOUT, // connect timeout ERR_SEND_FAILED, // send error, failed ERR_SEND_TIMEOUT, // send timeout @@ -39,58 +72,77 @@ namespace purelib { socket_event_except = 4, }; - class xxappl_pdu; // application layer protocol data unit. + typedef std::function vdcallback_t; + + class appl_pdu; // application layer protocol data unit. - typedef std::function xxappl_pdu_sent_callback_t; - typedef std::function&&)> xxappl_pdu_received_callback_t; + typedef std::function appl_pdu_send_callback_t; + typedef std::function&&)> appl_pdu_recv_callback_t; - struct xxp2p_io_ctx + struct p2p_io_ctx { xxsocket impl_; bool connected_; - P2PChannelType channel_type_ = TCP_P2P_UNKNOWN; + int channel_type_ = TCP_P2P_UNKNOWN; char buffer_[65536]; // recv buffer int offset_ = 0; // recv buffer offset - + std::vector receiving_pdu_; int expected_pdu_length_ = -1; int error = 0; - std::mutex send_queue_mtx_; - std::queue send_queue_; + std::recursive_mutex send_queue_mtx_; + std::deque send_queue_; void reset(); }; + class deadline_timer; + // A tcp client support P2P - class xxtcp_client : public xxp2p_io_ctx + class async_tcp_client : public p2p_io_ctx { - friend struct xxp2p_io_ctx; + friend struct p2p_io_ctx; public: // End user pdu decode length func typedef bool(*decode_pdu_length_func)(const char* data, size_t datalen, int& len); - // BuildErrorInfoFunc - typedef std::vector(*build_error_func)(int errorcode, const char* errormsg); + // connection_lost_callback_t + typedef std::function connection_lost_callback_t; typedef std::function connect_listener; public: - xxtcp_client(); - ~xxtcp_client(); + async_tcp_client(); + ~async_tcp_client(); + + size_t get_received_pdu_count(void) const; - // call on main thread, TODO: implement - bool collect_received_pdu(float dt = 0); + // must be call on main thread(such cocos2d-x opengl thread) + void dispatch_received_pdu(int count = 1); // set endpoint of server. void set_endpoint(const char* address, const char* addressv6, u_short port); - // set callbacks + void switch_endpoint(const char* address, u_short port); + + // set callbacks, required API, must call by user + /* + threadsafe_call: for cocos2d-x should be: + [](const vdcallback_t& callback) { + cocos2d::Director::getInstance()->getScheduler()->performFunctionInCocosThread([=]{ + callback(); + }); + } + */ void set_callbacks( decode_pdu_length_func decode_length_func, - build_error_func build_error_pdu_func, - const xxappl_pdu_received_callback_t& callback); + const connection_lost_callback_t& on_connection_lost, + const appl_pdu_recv_callback_t& callback, + const std::function& threadsafe_call); + + void set_connect_listener(const connect_listener& listener); // set connect and send timeouts. void set_timeouts(long timeo_connect, long timeo_send); @@ -98,6 +150,8 @@ namespace purelib { // start async socket service void start_service(int working_counter = 1); + void set_connect_wait_timeout(long seconds = -1/*-1: disable auto connect */); + // notify tcp_client to connect server void notify_connect(); @@ -108,10 +162,10 @@ namespace purelib { bool is_connected(void) const { return this->connected_; } // Gets network error code - ErrorCode get_errorno(void) { return error_; } + error_number get_errorno(void) { return static_cast(error_number_); } // post a async send request. - void async_send(std::vector&& data, const xxappl_pdu_sent_callback_t& callback = nullptr); + void async_send(std::vector&& data, const appl_pdu_send_callback_t& callback = nullptr); // *********** p2p support ***************** @@ -124,10 +178,17 @@ namespace purelib { // try to connect peer. local --> peer connection void p2p_async_connect(const ip::endpoint& ep); - // shutdown p2p + // shutdown p2p, TODO: implement void p2p_shutdown(void); + // timer support + void schedule_timer(deadline_timer*); + void cancel_timer(deadline_timer*); + private: + void perform_timeout_timers(); // ALL timer expired + + void get_wait_duration(timeval& tv, long long usec); void register_descriptor(const socket_native_type fd, int flags); void unregister_descriptor(const socket_native_type fd, int flags); @@ -138,24 +199,23 @@ namespace purelib { void service(void); - bool do_write(xxp2p_io_ctx*); - bool do_read(xxp2p_io_ctx*); - void move_received_pdu(xxp2p_io_ctx*); // move received properly pdu to recv queue + bool do_write(p2p_io_ctx*); + bool do_read(p2p_io_ctx*); + void move_received_pdu(p2p_io_ctx*); // move received properly pdu to recv queue - void handle_error(void); // TODO: add errorcode parameter + void handle_error(void); // TODO: add error_number parameter private: + bool switching_ = false; bool app_exiting_; bool thread_started_; + std::thread worker_thread_; std::string address_; std::string addressv6_; u_short port_; - // xxsocket impl_; - ErrorCode error_; - - int socket_error_; + int error_number_; // socket_error( >= -1) & application error(0 or < -1) int connect_timeout_; int send_timeout_; @@ -163,34 +223,47 @@ namespace purelib { bool connect_failed_; std::mutex recv_queue_mtx_; - std::queue> recv_queue_; // the recev_queue_ for connections: local-->server, local-->peer, peer-->local + std::deque> recv_queue_; // the recev_queue_ for connections: local-->server, local-->peer, peer-->local std::mutex connect_notify_mtx_; std::condition_variable connect_notify_cv_; + long connect_wait_timeout_; + + // select interrupter + select_interrupter interrupter_; + // timer support + std::vector timer_queue_; + std::recursive_mutex timer_queue_mtx_; // socket event set - fd_set readfds_, writefds_, excepfds_; + int maxfdp_; + enum { + read_op, + write_op, + except_op, + }; + fd_set fds_array_[3]; + // fd_set readfds_, writefds_, excepfds_; connect_listener connect_listener_; - xxappl_pdu_received_callback_t on_received_pdu_; + appl_pdu_recv_callback_t on_received_pdu_; decode_pdu_length_func decode_pdu_length_; - build_error_func build_error_pdu_; + connection_lost_callback_t on_connection_lost_; + std::function call_tsf_; bool idle_; bool suspended_ = false; long long total_connect_times_ = 0; - std::atomic working_counter_; // service working counter, default: 1 - // p2p support xxsocket p2p_acceptor_; // p2p: the acceptor for connections: peer-->local ip::endpoint p2p_peer_endpoint_; // p2p: this should tell by server - xxp2p_io_ctx p2p_channel1_; // p2p: connection: local ---> peer - xxp2p_io_ctx p2p_channel2_; // p2p: connection: peer ---> local - }; // xxtcp_client + p2p_io_ctx p2p_channel1_; // p2p: connection: local ---> peer + p2p_io_ctx p2p_channel2_; // p2p: connection: peer ---> local + }; // async_tcp_client }; /* namspace purelib::net */ }; /* namespace purelib */ #endif -#define tcpcli purelib::gc::singleton::instance() +#define tcpcli purelib::gc::singleton::instance() diff --git a/src/xxtcp_client.cpp b/src/async_tcp_client_experimental.cpp similarity index 37% rename from src/xxtcp_client.cpp rename to src/async_tcp_client_experimental.cpp index 8c1aad3cb099b6a67703b7cf82ade22180ea3446..b1fbdfb05542afe0e4296b9d0bcc689e4af1ec9f 100644 --- a/src/xxtcp_client.cpp +++ b/src/async_tcp_client_experimental.cpp @@ -1,75 +1,132 @@ -#include "oslib.h" -#include "xxtcp_client.h" +////////////////////////////////////////////////////////////////////////////////////////// +// A cross platform socket APIs, support ios & android & wp8 & window store universal app +// version: 2.3 +////////////////////////////////////////////////////////////////////////////////////////// +/* +The MIT License (MIT) + +Copyright (c) 2012-2016 halx99 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +#include "async_tcp_client.h" + + +#define _USING_IN_COCOS2DX 0 + +#define INET_ENABLE_VERBOSE_LOG 0 + +#if _USING_IN_COCOS2DX +#include "cocos2d.h" +#define INET_LOG(format,...) cocos2d::Director::getInstance()->getScheduler()->performFunctionInCocosThread([=]{cocos2d::log((format), ##__VA_ARGS__);}) +#else +#define INET_LOG(format,...) fprintf(stdout,(format "\n"),##__VA_ARGS__) +#endif #ifdef _WIN32 -#define msleep(msec) Sleep((msec)) -#define sleep(sec) msleep((sec) * 1000) #if !defined(WINRT) #include #pragma comment(lib, "winmm.lib") #endif -#else -#define msleep(msec) usleep((msec) * 1000) #endif -#define RECONNECT_DELAY 5000 // 5000 millseconds -#define TIMER_DURATION 100 // 100 miliseconds +#define MAX_WAIT_DURATION 5 * 60 * 1000 * 1000 // 5 minites + +#define MAX_BUSY_DELAY 1000 // 1 millisecond + +#define MAX_PDU_LEN SZ(10, M) -#define MAX_PDU_LEN 16384 +#define TSF_CALL(stmt) this->call_tsf_([=]{(stmt);}); namespace purelib { namespace inet { -class xxappl_pdu +class appl_pdu { public: - xxappl_pdu(std::vector&& right, const xxappl_pdu_sent_callback_t& callback) + appl_pdu(std::vector&& right, const appl_pdu_send_callback_t& callback, const std::chrono::microseconds& duration) { data_ = std::move(right); offset_ = 0; on_sent_ = callback; - timestamp_ = ::millitime(); + expire_time_ = std::chrono::steady_clock::now() + duration; + } + bool expired() const { + return (expire_time_ - std::chrono::steady_clock::now()).count() < 0; } std::vector data_; // sending data size_t offset_; // offset - xxappl_pdu_sent_callback_t on_sent_; - long long timestamp_; // In milliseconds + appl_pdu_send_callback_t on_sent_; + compatible_timepoint_t expire_time_; + + static void * operator new(size_t /*size*/) + { + return get_pool().get(); + } + + static void operator delete(void *p) + { + get_pool().release(p); + } + + static purelib::gc::object_pool& get_pool() + { + static purelib::gc::object_pool s_pool; + return s_pool; + } }; -void xxp2p_io_ctx::reset() +void p2p_io_ctx::reset() { connected_ = false; receiving_pdu_.clear(); offset_ = 0; expected_pdu_length_ = -1; error = 0; - std::queue empty_queue; - send_queue_.swap(empty_queue); if (this->impl_.is_open()) { this->impl_.close(); } } -xxtcp_client::xxtcp_client() : app_exiting_(false), +async_tcp_client::async_tcp_client() : app_exiting_(false), thread_started_(false), + interrupter_(), address_("192.168.1.104"), port_(8001), connect_timeout_(3), send_timeout_(3), decode_pdu_length_(nullptr), - error_(ErrorCode::ERR_OK), + error_(error_number::ERR_OK), idle_(true), - connect_failed_(false) + connect_failed_(false), + connect_wait_timeout_(-1) { - FD_ZERO(&readfds_); - FD_ZERO(&writefds_); - FD_ZERO(&excepfds_); + FD_ZERO(&fds_array_[read_op]); + FD_ZERO(&fds_array_[write_op]); + FD_ZERO(&fds_array_[read_op]); + maxfdp_ = 0; reset(); } -xxtcp_client::~xxtcp_client() +async_tcp_client::~async_tcp_client() { app_exiting_ = true; @@ -79,44 +136,87 @@ xxtcp_client::~xxtcp_client() close(); this->connect_notify_cv_.notify_all(); - while (working_counter_ > 0) { // wait all workers exited - msleep(1); - } + + if (this->worker_thread_.joinable()) + this->worker_thread_.join(); +} + +void async_tcp_client::set_timeouts(long timeo_connect, long timeo_send) +{ + this->connect_timeout_ = timeo_connect; + this->send_timeout_ = timeo_send; } -void xxtcp_client::set_endpoint(const char* address, const char* addressv6, u_short port) +void async_tcp_client::set_endpoint(const char* address, const char* addressv6, u_short port) { this->address_ = address; this->addressv6_ = address; this->port_ = port; } -void xxtcp_client::start_service(int working_counter) +void async_tcp_client::set_callbacks( + decode_pdu_length_func decode_length_func, + const connection_lost_callback_t& on_connection_lost, + const appl_pdu_recv_callback_t& callback, + const std::function& threadsafe_call) +{ + this->decode_pdu_length_ = decode_length_func; + this->on_received_pdu_ = callback; + this->on_connection_lost_ = on_connection_lost; + this->call_tsf_ = threadsafe_call; +} + +size_t async_tcp_client::get_received_pdu_count(void) const +{ + return recv_queue_.size(); +} + +void async_tcp_client::dispatch_received_pdu(int count) { + assert(this->on_received_pdu_ != nullptr); + + if (this->recv_queue_.empty()) + return; + + std::lock_guard autolock(this->recv_queue_mtx_); + do { + auto packet = std::move(this->recv_queue_.front()); + this->recv_queue_.pop_front(); + this->on_received_pdu_(std::move(packet)); + } while (!this->recv_queue_.empty() && --count > 0); +} + +void async_tcp_client::start_service(int /*working_counter*/) { if (!thread_started_) { thread_started_ = true; - // this->scheduleCollectResponse(); // - this->working_counter_ = working_counter; - for (auto i = 0; i < working_counter; ++i) { - std::thread t([this] { - // INETLOG("xxtcp_client thread running..."); - this->service(); - --working_counter_; - //cocos2d::log("p2s thread exited."); - }); - t.detach(); - } + worker_thread_ = std::thread([this] { + INET_LOG("async_tcp_client thread running..."); + this->service(); + INET_LOG("async_tcp_client thread exited."); + }); } } +void async_tcp_client::set_connect_listener(const connect_listener& listener) +{ + this->connect_listener_ = listener; +} + +void async_tcp_client::set_connect_wait_timeout(long seconds/*-1: disable auto connect */) +{ + this->connect_wait_timeout_ = seconds; +} -void xxtcp_client::wait_connect_notify() +void async_tcp_client::wait_connect_notify() { std::unique_lock autolock(connect_notify_mtx_); - connect_notify_cv_.wait(autolock); // wait 1 minutes, if no notify, wakeup self. + if (connect_wait_timeout_ == -1) + connect_notify_cv_.wait(autolock); + else + connect_notify_cv_.wait_for(autolock, std::chrono::seconds(connect_wait_timeout_)); } -void xxtcp_client::service() +void async_tcp_client::service() { #if defined(_WIN32) && !defined(WINRT) timeBeginPeriod(1); @@ -125,7 +225,7 @@ void xxtcp_client::service() if (this->suspended_) return; - while (!app_exiting_) + while (!app_exiting_) { bool connection_ok = impl_.is_open(); @@ -143,100 +243,92 @@ void xxtcp_client::service() // event loop - fd_set read_set, write_set, excep_set; + fd_set fds_array[3]; timeval timeout; for (; !app_exiting_;) { - idle_ = true; - - timeout.tv_sec = 0; // 5 minutes - timeout.tv_usec = 10 * 1000; // 10 milliseconds - - memcpy(&read_set, &readfds_, sizeof(fd_set)); - memcpy(&write_set, &writefds_, sizeof(fd_set)); - memcpy(&excep_set, &excepfds_, sizeof(fd_set)); - - int nfds = ::select(0, &read_set, &write_set, &excep_set, &timeout); + ::memcpy(&fds_array, this->fds_array_, sizeof(this->fds_array_)); + // @pitfall: If still have data to read, only wait 1 millseconds. + get_wait_duration(timeout, this->offset_ > 0 ? MAX_BUSY_DELAY : MAX_WAIT_DURATION); +#if INET_ENABLE_VERBOSE_LOG + INET_LOG("socket.select maxfdp:%d waiting... %ld milliseconds", maxfdp_, timeout.tv_sec * 1000 + timeout.tv_usec / 1000); +#endif + int nfds = ::select(maxfdp_, &(fds_array[read_op]), nullptr, nullptr, &timeout); +#if INET_ENABLE_VERBOSE_LOG + INET_LOG("socket.select waked up, retval=%d", nfds); +#endif if (nfds == -1) { - // log("select failed, error code: %d\n", GetLastError()); - msleep(TIMER_DURATION); - continue; // select again + int ec = xxsocket::get_last_errno(); + INET_LOG("socket.select failed, error code: %d, error msg:%s\n", ec, xxsocket::get_error_msg(ec)); + if (ec == EBADF || !this->impl_.is_open()) { + goto _L_error; + } + continue; // try select again. } - if (nfds == 0) + if (nfds == 0) { +#if INET_ENABLE_VERBOSE_LOG + INET_LOG("socket.select is timeout, do perform_timeout_timers()"); +#endif + } + // Reset the interrupter. + else if (nfds > 0 && FD_ISSET(this->interrupter_.read_descriptor(), &(fds_array[read_op]))) { - continue; + bool was_interrupt = interrupter_.reset(); +#if INET_ENABLE_VERBOSE_LOG + INET_LOG("socket.select waked up by interrupt, interrupter fd:%d, was_interrupt:%s", this->interrupter_.read_descriptor(), was_interrupt ? "true" : "false"); +#endif + --nfds; } - /* - ** check and handle readable sockets - */ - for (auto i = 0; i < excepfds_.fd_count; ++i) { - if (excepfds_.fd_array[i] == this->impl_) - { +#if 0 + // we should check whether the connection have exception before any operations. + if (FD_ISSET(this->impl_.native_handle(), &(fds_array[except_op]))) + { + int ec = xxsocket::get_last_errno(); + INET_LOG("socket.select exception triggered, error code: %d, error msg:%s\n", ec, xxsocket::get_error_msg(ec)); + goto _L_error; + } +#endif + if (nfds > 0 || this->offset_ > 0) { +#if INET_ENABLE_VERBOSE_LOG + INET_LOG("perform read operation..."); +#endif + if (!do_read(this)) { + // INET_LOG("do read failed..."); goto _L_error; } } - /* - ** check and handle readable sockets - */ - for (auto i = 0; i < read_set.fd_count; ++i) { - const auto readfd = read_set.fd_array[i]; - if (readfd == this->p2p_acceptor_) - { // process p2p connect request from peer - p2p_do_accept(); - } - else if (readfd == this->impl_) - { - if (!do_read(this)) - goto _L_error; - idle_ = false; - } - else if (readfd == this->p2p_channel2_.impl_) { - if (!do_read(&this->p2p_channel2_)) - { // read failed - this->p2p_channel2_.reset(); - } - } - else if (readfd == this->p2p_channel1_.impl_) { - if (this->p2p_channel1_.connected_) - { - if (!do_read(&this->p2p_channel1_)) - { // read failed - this->p2p_channel2_.reset(); - } - } - else { - printf("P2P: The connection local --> peer established. \n"); - this->p2p_channel1_.connected_ = true; - } + send_queue_mtx_.lock(); + // perform write operations + if (!this->send_queue_.empty()) { +#if INET_ENABLE_VERBOSE_LOG + INET_LOG("perform write operation..."); +#endif + if (!do_write(this)) + { // TODO: check would block? for client, may be unnecessary. + // INET_LOG("do write failed..."); + goto _L_error; + send_queue_mtx_.unlock(); } } - } - // perform write operations - if (!do_write(this)) - { // TODO: check would block? for client, may be unnecessory. - goto _L_error; - } - - if (this->p2p_channel1_.connected_) { - if (!do_write(&p2p_channel1_)) - p2p_channel1_.reset(); - } + perform_timeout_timers(); + send_queue_mtx_.unlock(); - if (this->p2p_channel1_.connected_) { - if (!do_write(&p2p_channel2_)) - p2p_channel2_.reset(); - } + /*if (this->p2p_channel1_.connected_) { + if (!do_write(&p2p_channel1_)) + p2p_channel1_.reset(); + } - // Avoid high Occupation CPU - if (idle_) { - msleep(1); + if (this->p2p_channel1_.connected_) { + if (!do_write(&p2p_channel2_)) + p2p_channel2_.reset(); + }*/ } continue; @@ -250,109 +342,136 @@ void xxtcp_client::service() #endif } -void xxtcp_client::close() +void async_tcp_client::close() { - if (impl_.is_open()) + if (impl_.is_open()) { + impl_.shutdown(); impl_.close(); + } + + interrupter_.interrupt(); } -void xxtcp_client::notify_connect() +void async_tcp_client::notify_connect() { std::unique_lock autolock(connect_notify_mtx_); connect_notify_cv_.notify_one(); } -void xxtcp_client::handle_error(void) +void async_tcp_client::handle_error(void) { socket_error_ = xxsocket::get_last_errno(); - const char* errs = xxsocket::get_error_msg(socket_error_); if (impl_.is_open()) { impl_.close(); } else { - // INETLOG("local close the connection!"); + INET_LOG("local close the connection!"); } - this->receiving_pdu_ = build_error_pdu_(socket_error_, errs);; - move_received_pdu(this); + connected_ = false; + + // @Notify connection lost + if (this->on_connection_lost_) { + TSF_CALL(on_connection_lost_(socket_error_, xxsocket::get_error_msg(socket_error_))); + } + + // @Clear all sending messages + this->send_queue_mtx_.lock(); + if (!send_queue_.empty()) { + for (auto pdu : send_queue_) + delete pdu; + send_queue_.clear(); + } + // this->send_queue_mtx_.unlock(); + + // @Notify all timers are cancelled. + // this->send_queue_mtx_.lock(); + //for (auto& timer : timer_queue_) + // timer->callback_(true); + this->timer_queue_.clear(); + this->send_queue_mtx_.unlock(); + + interrupter_.reset(); } -void xxtcp_client::register_descriptor(const socket_native_type fd, int flags) +void async_tcp_client::register_descriptor(const socket_native_type fd, int flags) { if ((flags & socket_event_read) != 0) { - FD_SET(fd, &this->readfds_); + FD_SET(fd, &(fds_array_[read_op])); } if ((flags & socket_event_write) != 0) { - FD_SET(fd, &this->writefds_); + FD_SET(fd, &(fds_array_[write_op])); } if ((flags & socket_event_except) != 0) { - FD_SET(fd, &this->excepfds_); + FD_SET(fd, &(fds_array_[except_op])); } + + if (maxfdp_ < static_cast(fd) + 1) + maxfdp_ = static_cast(fd) + 1; } -void xxtcp_client::unregister_descriptor(const socket_native_type fd, int flags) +void async_tcp_client::unregister_descriptor(const socket_native_type fd, int flags) { if ((flags & socket_event_read) != 0) { - FD_CLR(fd, &this->readfds_); + FD_CLR(fd, &(fds_array_[read_op])); } if ((flags & socket_event_write) != 0) { - FD_CLR(fd, &this->writefds_); + FD_CLR(fd, &(fds_array_[write_op])); } if ((flags & socket_event_except) != 0) { - FD_CLR(fd, &this->excepfds_); + FD_CLR(fd, &(fds_array_[except_op])); } } -void xxtcp_client::async_send(std::vector&& data, const xxappl_pdu_sent_callback_t& callback) +void async_tcp_client::async_send(std::vector&& data, const appl_pdu_send_callback_t& callback) { if (this->impl_.is_open()) { - auto pdu = new xxappl_pdu(std::move(data), callback); + auto pdu = new appl_pdu(std::move(data), callback, std::chrono::seconds(this->send_timeout_)); + + send_queue_mtx_.lock(); + send_queue_.push_back(pdu); + send_queue_mtx_.unlock(); - std::unique_lock autolock(send_queue_mtx_); - send_queue_.push(pdu); + interrupter_.interrupt(); } else { - // cocos2d::log("xxtcp_client::send failed, The connection not ok!!!"); + INET_LOG("async_tcp_client::send failed, The connection not ok!!!"); } } -void xxtcp_client::move_received_pdu(xxp2p_io_ctx* ctx) +void async_tcp_client::move_received_pdu(p2p_io_ctx* ctx) { - //cocos2d::log("moveReceivedpdu..."); - - std::unique_lock autolock(recv_queue_mtx_); - recv_queue_.push(std::move(ctx->receiving_pdu_)); - autolock.unlock(); +#if INET_ENABLE_VERBOSE_LOG + INET_LOG("move_received_pdu..."); +#endif + recv_queue_mtx_.lock(); + recv_queue_.push_back(std::move(ctx->receiving_pdu_)); // without data copy + recv_queue_mtx_.unlock(); ctx->expected_pdu_length_ = -1; - - // CCSCHTASKS->resumeTarget(this); } -bool xxtcp_client::connect(void) +bool async_tcp_client::connect(void) { if (connect_failed_) { - // simpleHttpReqServerIP(); connect_failed_ = false; } - //INETLOG("connecting server %s:%u...", address.c_str(), port); - //impl.open(); - //auto ep = xxsocket::resolve(this->address.c_str(), this->port); + INET_LOG("connecting server %s:%u...", address_.c_str(), port_); int ret = -1; this->connected_ = false; @@ -362,34 +481,29 @@ bool xxtcp_client::connect(void) } else if (flags & ipsv_ipv6) { // client is IPV6_Only - //cocos2d::log("Client needs a ipv6 server address to connect!"); + INET_LOG("Client needs a ipv6 server address to connect!"); ret = impl_.pconnect_n(this->addressv6_.c_str(), this->port_, this->connect_timeout_); } if (ret == 0) { // connect succeed, reset fds - this->connected_ = true; - - FD_ZERO(&readfds_); - FD_ZERO(&writefds_); - FD_ZERO(&excepfds_); + FD_ZERO(&fds_array_[read_op]); + FD_ZERO(&fds_array_[write_op]); + FD_ZERO(&fds_array_[except_op]); - auto fd = impl_.native_handle(); - register_descriptor(fd, socket_event_read | socket_event_except); - - std::unique_lock autolock(send_queue_mtx_); - std::queue emptypduQueue; - this->send_queue_.swap(emptypduQueue); + register_descriptor(interrupter_.read_descriptor(), socket_event_read); + register_descriptor(impl_.native_handle(), socket_event_read); impl_.set_nonblocking(true); expected_pdu_length_ = -1; - error_ = ErrorCode::ERR_OK; + error_ = error_number::ERR_OK; offset_ = 0; receiving_pdu_.clear(); + recv_queue_.clear(); - this->impl_.set_optval(SOL_SOCKET, SO_REUSEADDR, 1); + this->impl_.set_optval(SOL_SOCKET, SO_REUSEADDR, 1); // set opt for p2p - // INETLOG("connect server: %s:%u succeed.", address.c_str(), port); + INET_LOG("connect server: %s:%u succeed, fd=%d interrupter_fd=%d", address_.c_str(), port_, impl_.native_handle(), interrupter_.read_descriptor()); #if 0 // provided as API auto endp = this->impl_.local_endpoint(); @@ -412,8 +526,9 @@ bool xxtcp_client::connect(void) } #endif + this->connected_ = true; if (this->connect_listener_ != nullptr) { - this->connect_listener_(true, 0); + TSF_CALL(this->connect_listener_(true, 0)); } return true; @@ -422,18 +537,16 @@ bool xxtcp_client::connect(void) connect_failed_ = true; int ec = xxsocket::get_last_errno(); if (this->connect_listener_ != nullptr) { - /* CCRUNONGL([this, ec] { - connectListener(false, ec); - });*/ + TSF_CALL(this->connect_listener_(false, ec)); } - // INETLOG("connect server: %s:%u failed, error code:%d, error msg:%s!", address.c_str(), port, ec, xxsocket::get_error_msg(ec)); + INET_LOG("connect server: %s:%u failed, error code:%d, error msg:%s!", address_.c_str(), port_, ec, xxsocket::get_error_msg(ec)); return false; } } -bool xxtcp_client::do_write(xxp2p_io_ctx* ctx) +bool async_tcp_client::do_write(p2p_io_ctx* ctx) { bool bRet = false; @@ -443,50 +556,63 @@ bool xxtcp_client::do_write(xxp2p_io_ctx* ctx) if (!ctx->impl_.is_open()) break; - std::unique_lock autolock(ctx->send_queue_mtx_); if (!ctx->send_queue_.empty()) { auto& v = ctx->send_queue_.front(); auto bytes_left = v->data_.size() - v->offset_; n = ctx->impl_.send_i(v->data_.data() + v->offset_, bytes_left); if (n == bytes_left) { // All pdu bytes sent. - ctx->send_queue_.pop(); - /*CCRUNONGL([v] { - if (v->onSend != nullptr) - v->onSend(ErrorCode::ERR_OK); - v->release(); - });*/ + ctx->send_queue_.pop_front(); + this->call_tsf_([v] { +#if INET_ENABLE_VERBOSE_LOG + auto packetSize = v->data_.size(); + INET_LOG("async_tcp_client::do_write ---> A packet sent success, packet size:%d", packetSize); +#endif + if (v->on_sent_ != nullptr) + v->on_sent_(error_number::ERR_OK); + delete v; + }); } else if (n > 0) { // TODO: add time - if ((millitime() - v->timestamp_) < (send_timeout_ * 1000)) + if (!v->expired()) { // change offset, remain data will send next time. // v->data_.erase(v->data_.begin(), v->data_.begin() + n); v->offset_ += n; } else { // send timeout - ctx->send_queue_.pop(); - /*CCRUNONGL([v] { - if (v->onSend) - v->onSend(ErrorCode::ERR_SEND_TIMEOUT); - v->release(); - });*/ + ctx->send_queue_.pop_front(); + this->call_tsf_([v] { +#if INET_ENABLE_VERBOSE_LOG + auto packetSize = v->data_.size(); + INET_LOG("async_tcp_client::do_write ---> A packet sent timeout, packet size:%d", packetSize); +#endif + if (v->on_sent_) + v->on_sent_(error_number::ERR_SEND_TIMEOUT); + delete v; + }); } } else { // n <= 0, TODO: add time socket_error_ = xxsocket::get_last_errno(); if (SHOULD_CLOSE_1(n, socket_error_)) { - ctx->send_queue_.pop(); - /*CCRUNONGL([v] { - if (v->onSend) - v->onSend(ErrorCode::ERR_CONNECTION_LOST); - v->release(); - });*/ + ctx->send_queue_.pop_front(); + + int ec = socket_error_; + std::string errormsg = xxsocket::get_error_msg(ec); + + int timestamp = time(NULL); + INET_LOG("[%d]async_tcp_client::do_write failed, the connection should be closed, retval=%d, socket error:%d, detail:%s", timestamp, n, ec, errormsg.c_str()); + + this->call_tsf_([v] { + if (v->on_sent_) + v->on_sent_(error_number::ERR_CONNECTION_LOST); + delete v; + }); break; } } idle_ = false; } - autolock.unlock(); bRet = true; } while (false); @@ -494,7 +620,7 @@ bool xxtcp_client::do_write(xxp2p_io_ctx* ctx) return bRet; } -bool xxtcp_client::do_read(xxp2p_io_ctx* ctx) +bool async_tcp_client::do_read(p2p_io_ctx* ctx) { bool bRet = false; do { @@ -507,9 +633,9 @@ bool xxtcp_client::do_read(xxp2p_io_ctx* ctx) if (n == -1) n = 0; - - // INETLOG("xxtcp_client::doRead --- received data len: %d, buffer data len: %d", n, n + offset); - +#if INET_ENABLE_VERBOSE_LOG + INET_LOG("async_tcp_client::do_read --- received data len: %d, buffer data len: %d", n, n + ctx->offset_); +#endif if (ctx->expected_pdu_length_ == -1) { // decode length if (decode_pdu_length_(ctx->buffer_, ctx->offset_ + n, ctx->expected_pdu_length_)) { @@ -517,6 +643,8 @@ bool xxtcp_client::do_read(xxp2p_io_ctx* ctx) ctx->offset_ += n; } else { // ok + ctx->receiving_pdu_.reserve(ctx->expected_pdu_length_); // #perfomance, avoid memory reallocte. + auto bytes_transferred = n + ctx->offset_; ctx->receiving_pdu_.insert(ctx->receiving_pdu_.end(), ctx->buffer_, ctx->buffer_ + (std::min)(ctx->expected_pdu_length_, bytes_transferred)); if (bytes_transferred >= expected_pdu_length_) @@ -534,7 +662,7 @@ bool xxtcp_client::do_read(xxp2p_io_ctx* ctx) } } else { - error_ = ErrorCode::ERR_DPL_ILLEGAL_PDU; + error_ = error_number::ERR_DPL_ILLEGAL_PDU; break; } } @@ -542,7 +670,7 @@ bool xxtcp_client::do_read(xxp2p_io_ctx* ctx) auto bytes_transferred = n + ctx->offset_;// bytes transferred at this time if ((receiving_pdu_.size() + bytes_transferred) > MAX_PDU_LEN) // TODO: config MAX_PDU_LEN, now is 16384 { - error_ = ErrorCode::ERR_PDU_TOO_LONG; + error_ = error_number::ERR_PDU_TOO_LONG; break; } else { @@ -574,8 +702,14 @@ bool xxtcp_client::do_read(xxp2p_io_ctx* ctx) else { socket_error_ = xxsocket::get_last_errno(); if (SHOULD_CLOSE_0(n, socket_error_)) { + int ec = socket_error_; + std::string errormsg = xxsocket::get_error_msg(ec); + int timestamp = time(NULL); if (n == 0) { - //INETLOG("server close the connection!"); + INET_LOG("[%d]async_tcp_client::do_read failed, the server close the connection, retval=%d, socket error:%d, detail:%s", timestamp, n, ec, errormsg.c_str()); + } + else { + INET_LOG("[%d]async_tcp_client::do_read failed, the connection should be closed, retval=%d, socket error:%d, detail:%s", timestamp, n, ec, errormsg.c_str()); } break; } @@ -588,7 +722,98 @@ bool xxtcp_client::do_read(xxp2p_io_ctx* ctx) return bRet; } -void xxtcp_client::p2p_open() +void async_tcp_client::schedule_timer(deadline_timer* timer) +{ + std::lock_guard lk(this->send_queue_mtx_); + if (std::find(timer_queue_.begin(), timer_queue_.end(), timer) != timer_queue_.end()) + return; + + this->timer_queue_.push_back(timer); + + std::sort(this->timer_queue_.begin(), this->timer_queue_.end(), [](deadline_timer* lhs, deadline_timer* rhs) { + return lhs->wait_duration() > rhs->wait_duration(); + }); + + if (timer == *this->timer_queue_.begin()) + interrupter_.interrupt(); +} + +void async_tcp_client::cancel_timer(deadline_timer* timer) +{ + std::lock_guard lk(this->send_queue_mtx_); + + auto iter = std::find(timer_queue_.begin(), timer_queue_.end(), timer); + if (iter != timer_queue_.end()) { + timer->callback_(true); + timer_queue_.erase(iter); + } +} + +void async_tcp_client::perform_timeout_timers() +{ + if (timer_queue_.empty()) + return; + + std::vector loop_timers; + while (!this->timer_queue_.empty()) + { + auto earliest = timer_queue_.back(); + if (earliest->expired()) + { + timer_queue_.pop_back(); + TSF_CALL(earliest->callback_(false)); + if (earliest->loop_) { + earliest->expires_from_now(); + loop_timers.push_back(earliest); + } + } + else { + break; + } + } + + if (!loop_timers.empty()) { + this->timer_queue_.insert(this->timer_queue_.end(), loop_timers.begin(), loop_timers.end()); + std::sort(this->timer_queue_.begin(), this->timer_queue_.end(), [](deadline_timer* lhs, deadline_timer* rhs) { + return lhs->wait_duration() > rhs->wait_duration(); + }); + } +} + +void async_tcp_client::get_wait_duration(timeval& tv, long long usec) +{ + // If send_queue_ not empty, we should perform it immediately. + // so set socket.select timeout to ZERO. + this->send_queue_mtx_.lock(); + if (!this->send_queue_.empty()) + { + this->send_queue_mtx_.unlock(); + ::memset(&tv, 0x0, sizeof(tv)); + return; + } + + auto earliest = !this->timer_queue_.empty() ? timer_queue_.back() : nullptr; + this->send_queue_mtx_.unlock(); + + std::chrono::microseconds min_duration(usec); // microseconds + if (earliest != nullptr) { + auto duration = earliest->wait_duration(); + if (min_duration > duration) + min_duration = duration; + } + + usec = min_duration.count(); + + if (usec > 0) { + tv.tv_sec = usec / 1000000; + tv.tv_usec = usec % 1000000; + } + else { + ::memset(&tv, 0x0, sizeof(tv)); + } +} + +void async_tcp_client::p2p_open() { if (is_connected()) { if (this->p2p_acceptor_.reopen()) @@ -600,7 +825,7 @@ void xxtcp_client::p2p_open() } } -bool xxtcp_client::p2p_do_accept(void) +bool async_tcp_client::p2p_do_accept(void) { if (this->p2p_channel2_.impl_.is_open()) { // Just ignore other connect request for 1 <<-->> 1 connections. @@ -612,29 +837,6 @@ bool xxtcp_client::p2p_do_accept(void) this->p2p_channel2_.impl_ = this->p2p_acceptor_.accept(); return this->p2p_channel2_.impl_.is_open(); } -#if 0 -void xxtcp_client::dispatchResponseCallbacks(float delta) -{ - std::unique_lock autolock(this->recvQueueMtx); - if (!this->recvQueue.empty()) { - auto pdu = std::move(this->recvQueue.front()); - this->recvQueue.pop(); - - if (this->recvQueue.empty()) { - autolock.unlock(); - //CCSCHTASKS->pauseTarget(this); - } - else - autolock.unlock(); - if (onRecvpdu != nullptr) - this->onRecvpdu(std::move(pdu)); - } - else { - autolock.unlock(); - //CCSCHTASKS->pauseTarget(this); - } -} -#endif } /* namespace purelib::net */ } /* namespace purelib */ diff --git a/src/crypto_utils.cpp b/src/crypto_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b7ff7bfc0d87f8e8319ec1127236ff7b3e32eb1b --- /dev/null +++ b/src/crypto_utils.cpp @@ -0,0 +1,624 @@ +#include +#include +#include +#include "crypto_utils.h" + +#define MD6_SUPPORT 1 + +#if defined(MD6_SUPPORT) +#include "md6.h" +#endif +#include + +// Only AES ecb no need ivec +#define IVEC_DEF { \ + 0x00, 0x23, 0x4b, 0x89, 0xaa, 0x96, 0xfe, 0xcd, \ + 0xaf, 0x80, 0xfb, 0xf1, 0x78, 0xa2, 0x56, 0x21 \ + } + +static unsigned char s_shared_ivec[] = IVEC_DEF; + +static unsigned char s_shared_enc_ivec[] = IVEC_DEF; +static unsigned char s_shared_dec_ivec[] = IVEC_DEF; + +static AES_KEY s_shared_enc_key; +static AES_KEY s_shared_dec_key; + +#define local static +#define BAD_CAST (unsigned char*) +#define rrand(min,max) rand() % ((max) - (min)) + (min) +#define sz_align(d, a) (((d) + ((a) - 1)) & ~((a) - 1)) +#define align_size(size) align((unsigned int)(size), sizeof(void*)) +#define min(a,b) ( (a) <= (b) ? (a) : (b) ) + +uint8_t hex2chr(const uint8_t hex) +{ + return hex > 9 ? (hex - 10 + 'a') : (hex + '0'); +} + +uint8_t chr2hex(const uint8_t ch) +{ + return isdigit(ch) ? (ch - '0') : (ch - 'A' + 10); +} + +uint8_t hex2uchr(const uint8_t hex) +{ + return hex > 9 ? (hex - 10 + 'A') : (hex + '0'); +} + +uint8_t uchr2hex(const uint8_t ch) +{ + return isdigit(ch) ? (ch - '0') : (ch - 'A' + 10); +} + +char* hex2chrp(const uint8_t hex, char charp[2]) +{ + charp[0] = hex2chr( hex >> 4 ); + charp[1] = hex2chr( hex & 0x0f ); + return charp; +} + +uint8_t chrp2hex(const char* charp[2]) +{ + return 0; +} + +void hexs2chars(const void* source, unsigned int sourceLen, + char* dest, unsigned int destLen) +{ + int i = 0, j = 0; + int n = min(sourceLen, destLen); + // assert( (sourceLen << 1) <= destLen ); + + for(; i < n; ++i, j = i << 1) + { + (void)hex2chrp(((const uint8_t*)source) [i], dest + j); + } +} + +/* end of basic convertors */ + + +/* +** Simple MD5 implementation +** +*/ +// Constants are the integer part of the sines of integers (in radians) * 2^32. +local const uint32_t k[64] = { +0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee , +0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501 , +0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be , +0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821 , +0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa , +0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8 , +0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed , +0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a , +0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c , +0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70 , +0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05 , +0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665 , +0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039 , +0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1 , +0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1 , +0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 }; + +// r specifies the per-round shift amounts +local const uint32_t r[] = {7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, + 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, + 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, + 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21}; + +// leftrotate function definition +#define LEFTROTATE(x, c) (((x) << (c)) | ((x) >> (32 - (c)))) + +local void to_bytes(uint32_t val, uint8_t *bytes) +{ + bytes[0] = (uint8_t) val; + bytes[1] = (uint8_t) (val >> 8); + bytes[2] = (uint8_t) (val >> 16); + bytes[3] = (uint8_t) (val >> 24); +} + +local void to_chars(uint32_t value, char chars[32]) +{ + (void)hex2chrp( (uint8_t) value, chars); + (void)hex2chrp( (uint8_t) (value >> 8), chars + 2 ); + (void)hex2chrp( (uint8_t) (value >> 16), chars + 4 ); + (void)hex2chrp( (uint8_t) (value >> 24), chars + 6 ); + +} + +local uint32_t to_int32(uint8_t *bytes) +{ + return (uint32_t) bytes[0] + | ((uint32_t) bytes[1] << 8) + | ((uint32_t) bytes[2] << 16) + | ((uint32_t) bytes[3] << 24); +} + +void md5(const void* initial_msg, size_t initial_len, void* digest) +{ + // These vars will contain the hash + uint32_t h0, h1, h2, h3; + + // Message (to prepare) + uint8_t *msg = NULL; + + size_t new_len, offset; + uint32_t w[16]; + uint32_t a, b, c, d, i, f, g, temp; + + // Initialize variables - simple count in nibbles: + h0 = 0x67452301; + h1 = 0xefcdab89; + h2 = 0x98badcfe; + h3 = 0x10325476; + + //Pre-processing: + //append "1" bit to message + //append "0" bits until message length in bits ≡ 448 (mod 512) + //append length mod (2^64) to message + + for (new_len = initial_len + 1; new_len % (512/8) != 448/8; new_len++) + ; + + msg = (uint8_t*)malloc(new_len + 8); + memcpy(msg, initial_msg, initial_len); + msg[initial_len] = 0x80; // append the "1" bit; most significant bit is "first" + for (offset = initial_len + 1; offset < new_len; offset++) + msg[offset] = 0; // append "0" bits + + // append the len in bits at the end of the buffer. + to_bytes(initial_len << 3, msg + new_len); + // initial_len>>29 == initial_len*8>>32, but avoids overflow. + to_bytes(initial_len>>29, msg + new_len + 4); + + // Process the message in successive 512-bit chunks: + //for each 512-bit chunk of message: + for(offset=0; offset>29 == initial_len*8>>32, but avoids overflow. + to_bytes(initial_len >> 29, msg + new_len + 4); + + // Process the message in successive 512-bit chunks: + //for each 512-bit chunk of message: + for(offset=0; offset> 4 ); + buffer[2] = hex2uchr( ((uint8_t*)source) [index] % 16); + stringLen = 3; + } + + memcpy(wrptr, buffer, stringLen); + wrptr += stringLen; + } + + *destLen = wrptr - (char*)dest; + + return CODEC_OK; +} + +/* urldecode: destLen */ +int urldec(const void *source, unsigned int sourceLen, + void *dest, unsigned int *destLen) +{ + uint8_t tmpc = 0; + unsigned int index = 0; + uint8_t* wrptr = (uint8_t*)dest; + for( ; index < sourceLen; ++index ) + { + tmpc = 0; + if( ((const char*)source) [index] == '%') + { + tmpc = (uchr2hex( ((const char*)source) [index + 1] ) << 4 ); + tmpc |= uchr2hex( ((const char*)source) [index + 2] ); + index += 2; + } + else if( ((const char*)source)[index] == '+') + { + tmpc = ' '; + } + else + { + tmpc = ((const char*)source)[index]; + } + *wrptr++ = tmpc; + } + + *destLen = wrptr - (uint8_t*)dest; // save real destLen + + return CODEC_OK; +} + +/* +** aes utils +*/ +/// AES ecb +void crypto::aes::detail::ecb_encrypt(const void* in, size_t inlen, + void* out, size_t outlen, const void* private_key, int keybits) +{ + assert((inlen % AES_BLOCK_SIZE) == 0); + + static const int slice_size = AES_BLOCK_SIZE; + + AES_KEY aes_key; + ossl_aes_set_encrypt_key((unsigned char *)private_key, keybits, &aes_key); + + // const size_t total_bytes = inlen; + size_t remain_bytes = inlen; + while (remain_bytes > 0) + { + /* if(remain_bytes > slice_size) {*/ + ossl_aes_encrypt((const unsigned char*)in, (unsigned char*)out, &aes_key); + in = (const char*)in + slice_size; + out = (char*)out + slice_size; + remain_bytes -= slice_size; + //} + //else { + // // encrypt last less AES_BLOCK_SIZE bytes + // AES_encrypt((const unsigned char*)in, (unsigned char*)out, &aes_key); + // remain_bytes = 0; + //} + } +} + +void crypto::aes::detail::ecb_decrypt(const void* in, size_t inlen, + void* out, size_t& outlen, const void* private_key, int keybits) +{ + static const int slice_size = AES_BLOCK_SIZE; + + AES_KEY aes_key; + ossl_aes_set_decrypt_key((unsigned char *)private_key, keybits, &aes_key); + + // const size_t total_bytes = inlen; + size_t remain_bytes = inlen; + outlen = 0; + while (remain_bytes > 0) + { + ossl_aes_decrypt((const unsigned char*)in, (unsigned char*)out, &aes_key); + if (remain_bytes > AES_BLOCK_SIZE) + { + outlen += (slice_size); + } + else { + size_t padding_size = *((unsigned char*)out + slice_size - 1); + outlen += (slice_size - padding_size); + } + + in = (const char*)in + slice_size; + out = (char*)out + slice_size; + remain_bytes -= slice_size; + } +} + +/// AES cbc +void crypto::aes::detail::cbc_encrypt(const void* in, size_t inlen, + void* out, size_t outlen, const void* private_key, int keybits) +{ + assert(inlen == outlen); + + unsigned char ivec[16]; + memcpy(ivec, s_shared_ivec, sizeof(ivec)); + + AES_KEY aes_key; + ossl_aes_set_encrypt_key((unsigned char *)private_key, keybits, &aes_key); + + ossl_aes_cbc_encrypt((const unsigned char*)in, (unsigned char*)out, outlen, &aes_key, ivec, AES_ENCRYPT); +} + +void crypto::aes::detail::cbc_decrypt(const void* in, size_t inlen, + void* out, size_t& outlen, const void* private_key, int keybits) +{ + unsigned char ivec[16]; + memcpy(ivec, s_shared_ivec, sizeof(ivec)); + + AES_KEY aes_key; + ossl_aes_set_decrypt_key((unsigned char *)private_key, keybits, &aes_key); + + ossl_aes_cbc_encrypt((const unsigned char*)in, (unsigned char*)out, inlen, &aes_key, ivec, AES_DECRYPT); + + size_t padding_size = ( (unsigned char*)out ) [inlen - 1]; + if (inlen > padding_size) + outlen = inlen - padding_size; +} + +/// AES cbc partial +void crypto::aes::detail::set_ivec(const void* ivec, size_t) +{ + memcpy(s_shared_ivec, ivec, sizeof(s_shared_ivec)); +} + +const void* crypto::aes::detail::get_ivec() +{ + return s_shared_ivec; +} + +void crypto::aes::detail::cbc_encrypt_init(const void* private_key, int keybits) +{ + memcpy(s_shared_enc_ivec, s_shared_ivec, sizeof(s_shared_enc_ivec)); + ossl_aes_set_encrypt_key((const unsigned char*)private_key, keybits, &s_shared_enc_key); +} + +void crypto::aes::detail::cbc_decrypt_init(const void* private_key, int keybits) +{ + memcpy(s_shared_dec_ivec, s_shared_ivec, sizeof(s_shared_enc_ivec)); + ossl_aes_set_decrypt_key((const unsigned char*)private_key, keybits, &s_shared_dec_key); +} + +void crypto::aes::detail::cbc_encrypt_init(const void* in, size_t inlen, + void* out, size_t outlen, + const void* private_key, int keybits) +{ + memcpy(s_shared_enc_ivec, s_shared_ivec, sizeof(s_shared_enc_ivec)); + ossl_aes_set_encrypt_key((const unsigned char*)private_key, keybits, &s_shared_enc_key); + + cbc_encrypt_block(in, inlen, out, outlen); +} + +void crypto::aes::detail::cbc_decrypt_init(const void* in, size_t inlen, + void* out, size_t outlen, + const void* private_key, int keybits) +{ + memcpy(s_shared_dec_ivec, s_shared_ivec, sizeof(s_shared_enc_ivec)); + ossl_aes_set_decrypt_key((const unsigned char*)private_key, keybits, &s_shared_dec_key); + + cbc_decrypt_block(in, inlen, out, outlen); +} + +void crypto::aes::detail::cbc_encrypt_block(const void* in, size_t inlen, + void* out, size_t outlen) +{ + assert(inlen == outlen); + + ossl_aes_cbc_encrypt((const unsigned char*)in, (unsigned char*)out, outlen, &s_shared_enc_key, s_shared_enc_ivec, AES_ENCRYPT); +} + +void crypto::aes::detail::cbc_decrypt_block(const void* in, size_t inlen, void* out, size_t outlen) +{ + ossl_aes_cbc_encrypt((const unsigned char*)in, (unsigned char*)out, inlen, &s_shared_dec_key, s_shared_dec_ivec, AES_DECRYPT); +} diff --git a/src/crypto_utils.h b/src/crypto_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..bf2bd94fbbc6c21d6f88bb49d719efdf16b16518 --- /dev/null +++ b/src/crypto_utils.h @@ -0,0 +1,356 @@ +// +// Copyright (c) 2014-2015 purelib - All Rights Reserved +// +#ifndef _CRYPTO_UTILS_H_ +#define _CRYPTO_UTILS_H_ +#include +#include +#include +#include "aes.h" +#include "md5.h" +#include "libb64.h" +#include "mathext.h" + +//#ifdef __cplusplus +//extern "C" +//{ +//#endif + +/* + * This package supports both compile-time and run-time determination of CPU + * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be + * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is + * defined as non-zero, the code will be compiled to run only on big-endian + * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to + * run on either big- or little-endian CPUs, but will run slightly less + * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined. + */ + +#define CODEC_OK 0 +#define CODEC_BAD_ALLOC -2 + + +/* basic char convertors */ +uint8_t hex2uchr(const uint8_t hex); + +uint8_t uchr2hex(const uint8_t ch); + +uint8_t hex2chr(const uint8_t hex); + +uint8_t chr2hex(const uint8_t ch); + +char* hex2chrp(const uint8_t hex, char charp[2]); + +uint8_t chrp2hex(const char* charp[2]); + +/* convert hexstream to charstream */ +void hexs2chars(const void* source, unsigned int sourceLen, + char* dest, unsigned int destLen); +/* -- end of basic convertors -- */ + +/* Simple MD5 implementation, the return is a hexstream */ +void md5(const void* initial_msg, size_t initial_len, void* digest); + +/* Simple MD5 implementation, the return is a hexstream */ +void md5chars(const void* initial_msg, size_t initial_len, char chars[32]); + +/* MD5 V3: implement by call the openssl-md5 library, the return is a hexstream*/ +// void md5_v3(const void* source, unsigned int sourceLen, void* dest); + +/* Simple MD6 implementation, the return is a hexstream*/ +void md6(const void* source, unsigned int sourceLen, void* dest, unsigned int hashByteLen); + +/* Simple MD6 implementation, the return is a hexstream*/ +void md6chars(const void* source, unsigned int sourceLen, char* dest, unsigned int hashByteLen); + +/* base 64 encode: destLen should be set sourceLen * 2 */ +int base64enc(const void *source, unsigned int sourceLen, + void *dest, unsigned int *destLen); +/* base 64 decode: destLen should be set sourceLen */ +int base64dec (const void *source, unsigned int sourceLen, + void *dest, unsigned int *destLen); + +/* urlencode(RFC1738 standard implement): destLen should be sourceLen * 3. +** +** remark: php urlencode ' ' to '+'; but php urldecode can decode both +** RFC1738 encode-text and php urlencode. +*/ +int urlenc(const void *source, unsigned int sourceLen, + void *dest, unsigned int *destLen); + +/* urldecode: the destLen should be sourceLen +** +* remark: support decode RFC1738 encode-text and php urlencode. +*/ +int urldec(const void *source, unsigned int sourceLen, + void *dest, unsigned int *destLen); + +//#ifdef __cplusplus +//} /* end extern "C" */ +//#endif + +/// +/// all follow api regardless input as alignment BLOCK_SIZE: 16 +/// overlapped api +/// + +#include +#include + +namespace crypto { + + namespace aes { + + // 摘要: + // 指定用于加密的块密码模式。 + enum CipherMode + { + // 摘要: + // 密码块链 (CBC) 模式引入了反馈。每个纯文本块在加密前,通过按位“异或”操作与前一个块的密码文本结合。这样确保了即使纯文本包含许多相同的块,这些块中的每一个也会加密为不同的密码文本块。在加密块之前,初始化向量通过按位“异或”操作与第一个纯文本块结合。如果密码文本块中有一个位出错,相应的纯文本块也将出错。此外,后面的块中与原出错位的位置相同的位也将出错。 + CBC = 1, + // + // 摘要: + // 电子密码本 (ECB) 模式分别加密每个块。这意味着任何纯文本块只要相同并且在同一消息中,或者在用相同的密钥加密的不同消息中,都将被转换成同样的密码文本块。如果要加密的纯文本包含大量重复的块,则逐块破解密码文本是可行的。另外,随时准备攻击的对手可能在您没有察觉的情况下替代和交换个别的块。如果密码文本块中有一个位出错,相应的整个纯文本块也将出错。 + ECB = 2, + // + // 摘要: + // 输出反馈 (OFB) 模式将少量递增的纯文本处理成密码文本,而不是一次处理整个块。此模式与 CFB 相似;这两种模式的唯一差别是移位寄存器的填充方式不同。如果密码文本中有一个位出错,纯文本中相应的位也将出错。但是,如果密码文本中有多余或者缺少的位,则那个位之后的纯文本都将出错。 + OFB = 3, + // + // 摘要: + // 密码反馈 (CFB) 模式将少量递增的纯文本处理成密码文本,而不是一次处理整个块。该模式使用在长度上为一个块且被分为几部分的移位寄存器。例如,如果块大小为 + // 8 个字节,并且每次处理一个字节,则移位寄存器被分为 8 个部分。如果密码文本中有一个位出错,则一个纯文本位出错,并且移位寄存器损坏。这将导致接下来若干次递增的纯文本出错,直到出错位从移位寄存器中移出为止。 + CFB = 4, + // + // 摘要: + // 密码文本窃用 (CTS) 模式处理任何长度的纯文本并产生长度与纯文本长度匹配的密码文本。除了最后两个纯文本块外,对于所有其他块,此模式与 CBC + // 模式的行为相同。 + CTS = 5, + }; + + // 摘要: + // 指定在消息数据块比加密操作所需的全部字节数短时应用的填充类型。 + enum PaddingMode + { + // 摘要: + // 不填充。 + None = 1, + // + // 摘要: + // PKCS #7 填充字符串由一个字节序列组成,每个字节填充该字节序列的长度。 + PKCS7 = 2, + // + // 摘要: + // 填充字符串由设置为零的字节组成。 + Zeros = 3, + // + // 摘要: + // ANSIX923 填充字符串由一个字节序列组成,此字节序列的最后一个字节填充字节序列的长度,其余字节均填充数字零。 + ANSIX923 = 4, + // + // 摘要: + // ISO10126 填充字符串由一个字节序列组成,此字节序列的最后一个字节填充字节序列的长度,其余字节填充随机数据。 + ISO10126 = 5, + }; + + #define _BYTE_SEQ_CONT _ByteSeqCont + + static const char* DEFAULT_KEY = "ZQnNQmA1iIQ3z3ukoPoATdE88OJ0qsMm"; + + namespace detail { + + namespace padding{ + + template + inline size_t PKCS7(_BYTE_SEQ_CONT& plaintext, size_t blocksize = AES_BLOCK_SIZE) + { + static_assert(sizeof(typename _BYTE_SEQ_CONT::value_type) == 1, "PKCS7: only allow stl sequently byte conatiner!"); + size_t padding_size = blocksize - plaintext.size() % blocksize; + for (size_t offst = 0; offst < padding_size; ++offst) + { + plaintext.push_back((char)padding_size); + } + return padding_size; + } + + template + inline size_t ZEROS(_BYTE_SEQ_CONT& plaintext, size_t blocksize = AES_BLOCK_SIZE) + { + static_assert(sizeof(_BYTE_SEQ_CONT::value_type) == 1, "ZEROS: only allow stl sequently byte conatiner!"); + size_t padding_size = blocksize - plaintext.size() % blocksize; + for (size_t offst = 0; offst < padding_size; ++offst) + { + plaintext.push_back((char)0); + } + return padding_size; + } + + template + inline size_t ANSIX923(_BYTE_SEQ_CONT& plaintext, size_t blocksize = AES_BLOCK_SIZE) + { + static_assert(sizeof(_BYTE_SEQ_CONT::value_type) == 1, "ANSIX923: only allow stl sequently byte conatiner!"); + size_t padding_size = blocksize - plaintext.size() % blocksize; + for (size_t offst = 0; offst < padding_size - 1; ++offst) + { + plaintext.push_back((char)0); + } + plaintext.push_back((char)padding_size); + return padding_size; + } + + template + inline size_t ISO10126(_BYTE_SEQ_CONT& plaintext, size_t blocksize = AES_BLOCK_SIZE) + { + static_assert(sizeof(_BYTE_SEQ_CONT::value_type) == 1, "ISO10126: only allow stl sequently byte conatiner!"); + size_t padding_size = blocksize - plaintext.size() % blocksize; + for (size_t offst = 0; offst < padding_size - 1; ++offst) + { + plaintext.push_back((char)(unsigned char)mathext::rrand(0, 256)); + } + plaintext.push_back((char)padding_size); + return padding_size; + } + + template + inline _BYTE_SEQ_CONT PKCS7(size_t datasize, size_t blocksize = AES_BLOCK_SIZE) + { + static_assert(sizeof(_BYTE_SEQ_CONT::value_type) == 1, "ISO10126: only allow stl sequently byte conatiner!"); + _BYTE_SEQ_CONT padding; + size_t padding_size = blocksize - datasize % blocksize; + for (size_t offst = 0; offst < padding_size; ++offst) + { + padding.push_back((char)padding_size); + } + return std::move(padding); + } + + template + inline _BYTE_SEQ_CONT ZEROS(size_t datasize, size_t blocksize = AES_BLOCK_SIZE) + { + static_assert(sizeof(_BYTE_SEQ_CONT::value_type) == 1, "ISO10126: only allow stl sequently byte conatiner!"); + _BYTE_SEQ_CONT padding; + size_t padding_size = blocksize - datasize % blocksize; + for (size_t offst = 0; offst < padding_size; ++offst) + { + padding.push_back((char)0); + } + return std::move(padding); + } + + template + inline _BYTE_SEQ_CONT ANSIX923(size_t datasize, size_t blocksize = AES_BLOCK_SIZE) + { + static_assert(sizeof(_BYTE_SEQ_CONT::value_type) == 1, "ISO10126: only allow stl sequently byte conatiner!"); + _BYTE_SEQ_CONT padding; + size_t padding_size = blocksize - datasize % blocksize; + for (size_t offst = 0; offst < padding_size - 1; ++offst) + { + padding.push_back((char)0); + } + padding.push_back((char)padding_size); + return std::move(padding); + } + + template + inline _BYTE_SEQ_CONT ISO10126(size_t datasize, size_t blocksize = AES_BLOCK_SIZE) + { + static_assert(sizeof(_BYTE_SEQ_CONT::value_type) == 1, "ISO10126: only allow stl sequently byte conatiner!"); + _BYTE_SEQ_CONT padding; + size_t padding_size = blocksize - datasize % blocksize; + for (size_t offst = 0; offst < padding_size - 1; ++offst) + { + padding.push_back((char)(unsigned char)mathext::rrand(0, 256)); + } + padding.push_back((char)padding_size); + return std::move(padding); + } + + + inline size_t PKCS7(size_t datasize, char padding[16], size_t blocksize = AES_BLOCK_SIZE) + { + size_t padding_size = blocksize - datasize % blocksize; + for (size_t offst = 0; offst < padding_size; ++offst) + { + padding[AES_BLOCK_SIZE - 1 - offst] = (unsigned char)padding_size; + } + return padding_size; + } + + inline size_t ZEROS(size_t datasize, char padding[16], size_t blocksize = AES_BLOCK_SIZE) + { + size_t padding_size = blocksize - datasize % blocksize; + for (size_t offst = 0; offst < padding_size; ++offst) + { + padding[AES_BLOCK_SIZE - 1 - offst] = 0; + } + return padding_size; + } + + inline size_t ANSIX923(size_t datasize, char padding[16], size_t blocksize = AES_BLOCK_SIZE) + { + size_t padding_size = blocksize - datasize % blocksize; + padding[AES_BLOCK_SIZE - 1] = (unsigned char)padding_size; + for (size_t offst = 1; offst < padding_size; ++offst) + { + padding[AES_BLOCK_SIZE - 1 - offst] = 0; + } + return padding_size; + } + + inline size_t ISO10126(size_t datasize, char padding[16], size_t blocksize = AES_BLOCK_SIZE) + { + size_t padding_size = blocksize - datasize % blocksize; + padding[AES_BLOCK_SIZE - 1] = (unsigned char)padding_size; + for (size_t offst = 1; offst < padding_size; ++offst) + { + padding[AES_BLOCK_SIZE - 1 - offst] = (unsigned char)mathext::rrand(0, 256); + } + return padding_size; + } + } + + /// AES ecb + void ecb_encrypt(const void* in, size_t inlen, + void* out, size_t outlen, const void* private_key, int keybits = 256); + void ecb_decrypt(const void* in, size_t inlen, + void* out, size_t& outlen, const void* private_key, int keybits = 256); + + /// AES cbc + void cbc_encrypt(const void* in, size_t inlen, + void* out, size_t outlen, const void* private_key, int keybits = 256); + + void cbc_decrypt(const void* in, size_t inlen, + void* out, size_t& outlen, const void* private_key, int keybits = 256); + + /// AES cbc partial encrypt/decrypt + void set_ivec(const void* ivec, size_t len = AES_BLOCK_SIZE /* always AES_BLOCK_SIZE 16*/); + + /// the size always 16 bytes + const void* get_ivec(); + + void cbc_encrypt_init(const void* private_key, int keybits = 256); + + void cbc_decrypt_init(const void* private_key, int keybits = 256); + + void cbc_encrypt_init(const void* in, size_t inlen, + void* out, size_t outlen, + const void* private_key, int keybits = 256); + + void cbc_decrypt_init(const void* in, size_t inlen, + void* out, size_t outlen, + const void* private_key, int keybits = 256); + + void cbc_encrypt_block(const void* in, size_t inlen, + void* out, size_t outlen); + + void cbc_decrypt_block(const void* in, size_t inlen, + void* out, size_t outlen); + }; + }; +}; + +#endif /* _CRYPTO_UTILS_H_ */ +/* +* Copyright (c) 2012-2016 by halx99 ALL RIGHTS RESERVED. +* Consult your license regarding permissions and restrictions. +V2.0:2016 */ diff --git a/src/crypto_wrapper.cpp b/src/crypto_wrapper.cpp new file mode 100644 index 0000000000000000000000000000000000000000..405d02a1c6ea89bee9b661cbdbfd9795cad568a3 --- /dev/null +++ b/src/crypto_wrapper.cpp @@ -0,0 +1,626 @@ +#define _ZLIB_SUPPORT 1 +#define MD6_SUPPORT 1 + +#if defined(_WIN32) +#ifdef _ZLIB_SUPPORT +#if !defined(WINRT) +#pragma comment(lib, "libzlib.lib") +#else +#pragma comment(lib, "zlib.lib") +#endif +#else +#include "zlib.h" +#endif +#endif +#include +#include "crypto_wrapper.h" +#if defined(MD6_SUPPORT) +#include "md6.h" +#endif +#include +#include +#include "xxfsutility.h" + +#define HASH_FILE_BUFF_SIZE 1024 + +#ifdef _ZLIB_SUPPORT +#include "win32-specific/zlib/include/zlib.h" +#endif + +using namespace purelib; + +template +_ByteSeqCont zlib_compress(const unmanaged_string& in, int level) +{ + // calc destLen + auto destLen = ::compressBound(in.size()); + _ByteSeqCont out(destLen, '\0'); + + // do compress + int ret = ::compress2((Bytef*)(&out.front()), &destLen, (const Bytef*)in.c_str(), in.size(), level); + + if (ret == Z_OK) + { + out.resize(destLen); + } + return std::move(out); +} + +template +_ByteSeqCont zlib_deflate(const unmanaged_string& in, int level) +{ + int err; + Bytef buffer[128]; + z_stream d_stream; /* compression stream */ + + // strcpy((char*)buffer, "garbage"); + + d_stream.zalloc = nullptr; + d_stream.zfree = nullptr; + d_stream.opaque = (voidpf)0; + + d_stream.next_in = (Bytef*)in.c_str(); + d_stream.avail_in = in.size(); + d_stream.next_out = buffer; + d_stream.avail_out = sizeof(buffer); + + _ByteSeqCont output; + + err = deflateInit(&d_stream, level); + if (err != Z_OK) // TODO: log somthing + return std::move(output); + + output.reserve(in.size()); + + for (;;) + { + err = deflate(&d_stream, Z_FINISH); + + if (err == Z_STREAM_END) + { + output.insert(output.end(), buffer, buffer + sizeof(buffer) - d_stream.avail_out); + break; + } + + switch (err) + { + case Z_NEED_DICT: + err = Z_DATA_ERROR; + case Z_DATA_ERROR: + case Z_MEM_ERROR: + deflateEnd(&d_stream); + output.clear(); + return std::move(output); + } + + // not enough buffer ? + if (err != Z_STREAM_END) + { + output.insert(output.end(), buffer, buffer + sizeof(buffer)); + + d_stream.next_out = buffer; + d_stream.avail_out = sizeof(buffer); + } + } + + deflateEnd(&d_stream); + if (err != Z_STREAM_END) + { + output.clear(); + } + + return std::move(output); +} + +template +_ByteSeqCont zlib_inflate(const unmanaged_string& compr) +{ // inflate + int err; + Bytef buffer[128]; + z_stream d_stream; /* decompression stream */ + + // strcpy((char*)buffer, "garbage"); + + d_stream.zalloc = nullptr; + d_stream.zfree = nullptr; + d_stream.opaque = (voidpf)0; + + d_stream.next_in = (Bytef*)compr.c_str(); + d_stream.avail_in = compr.size(); + d_stream.next_out = buffer; + d_stream.avail_out = sizeof(buffer); + _ByteSeqCont output; + err = inflateInit(&d_stream); + if (err != Z_OK) // TODO: log somthing + return std::move(output); + // CHECK_ERR(err, "inflateInit"); + + output.reserve(compr.size() << 2); + for (;;) + { + err = inflate(&d_stream, Z_NO_FLUSH); + + if (err == Z_STREAM_END) + { + output.insert(output.end(), buffer, buffer + sizeof(buffer) - d_stream.avail_out); + break; + } + + switch (err) + { + case Z_NEED_DICT: + err = Z_DATA_ERROR; + case Z_DATA_ERROR: + case Z_MEM_ERROR: + goto _L_end; + } + + // not enough memory ? + if (err != Z_STREAM_END) + { + // *out = (unsigned char*)realloc(*out, bufferSize * BUFFER_INC_FACTOR); + output.insert(output.end(), buffer, buffer + sizeof(buffer)); + + d_stream.next_out = buffer; + d_stream.avail_out = sizeof(buffer); + } + } + +_L_end: + inflateEnd(&d_stream); + if (err != Z_STREAM_END) + { + output.clear(); + } + + return std::move(output); +} + +// inflate alias +template +_ByteSeqCont zlib_uncompress(const unmanaged_string& in) +{ + return zlib_inflate<_ByteSeqCont>(in); +} + +// gzip +template +_ByteSeqCont zlib_gzcompr(const unmanaged_string& in, int level) +{ + int err; + Bytef buffer[128]; + z_stream d_stream; /* compression stream */ + + // strcpy((char*)buffer, "garbage"); + + d_stream.zalloc = nullptr; + d_stream.zfree = nullptr; + d_stream.opaque = (voidpf)0; + + d_stream.next_in = (Bytef*)in.c_str(); + d_stream.avail_in = in.size(); + d_stream.next_out = buffer; + d_stream.avail_out = sizeof(buffer); + _ByteSeqCont output; + err = deflateInit2(&d_stream, level, Z_DEFLATED, MAX_WBITS + 16, MAX_MEM_LEVEL - 1, Z_DEFAULT_STRATEGY); + if (err != Z_OK) // TODO: log somthing + return std::move(output); + + for (;;) + { + err = deflate(&d_stream, Z_FINISH); + + if (err == Z_STREAM_END) + { + output.insert(output.end(), buffer, buffer + sizeof(buffer) - d_stream.avail_out); + break; + } + + switch (err) + { + case Z_NEED_DICT: + err = Z_DATA_ERROR; + case Z_DATA_ERROR: + case Z_MEM_ERROR: + goto _L_end; + } + + // not enough buffer ? + if (err != Z_STREAM_END) + { + output.insert(output.end(), buffer, buffer + sizeof(buffer)); + + d_stream.next_out = buffer; + d_stream.avail_out = sizeof(buffer); + } + } + +_L_end: + deflateEnd(&d_stream); + if (err != Z_STREAM_END) + { + output.clear(); + } + + return std::move(output); +} + +template +_ByteSeqCont zlib_gzuncompr(const unmanaged_string& compr) +{ // inflate + int err; + Bytef buffer[128]; + z_stream d_stream; /* decompression stream */ + + // strcpy((char*)buffer, "garbage"); + + d_stream.zalloc = nullptr; + d_stream.zfree = nullptr; + d_stream.opaque = (voidpf)0; + + d_stream.next_in = (Bytef*)compr.c_str(); + d_stream.avail_in = compr.size(); + d_stream.next_out = buffer; + d_stream.avail_out = sizeof(buffer); + _ByteSeqCont output; + err = inflateInit2(&d_stream, MAX_WBITS + 16); + if (err != Z_OK) // TODO: log somthing + return std::move(output); + // CHECK_ERR(err, "inflateInit"); + output.reserve(compr.size() << 2); + + for (;;) + { + err = inflate(&d_stream, Z_NO_FLUSH); + + if (err == Z_STREAM_END) + { + output.insert(output.end(), buffer, buffer + sizeof(buffer) - d_stream.avail_out); + break; + } + + switch (err) + { + case Z_NEED_DICT: + err = Z_DATA_ERROR; + case Z_DATA_ERROR: + case Z_MEM_ERROR: + goto _L_end; + } + + // not enough memory ? + if (err != Z_STREAM_END) + { + // *out = (unsigned char*)realloc(*out, bufferSize * BUFFER_INC_FACTOR); + output.insert(output.end(), buffer, buffer + sizeof(buffer)); + + d_stream.next_out = buffer; + d_stream.avail_out = sizeof(buffer); + } + } + +_L_end: + inflateEnd(&d_stream); + if (err != Z_STREAM_END) + { + output.clear(); + } + + return std::move(output); +} + +std::string crypto::zlib::compress(const unmanaged_string& in, int level) +{ + return zlib_compress(in, level); +} +std::string crypto::zlib::uncompress(const unmanaged_string& in) +{ + return zlib_uncompress(in); +} +std::string crypto::zlib::deflate(const unmanaged_string& in, int level) +{ + return zlib_deflate(in, level); +} +std::string crypto::zlib::inflate(const unmanaged_string& in) +{ + return zlib_inflate(in); +} +std::string crypto::zlib::gzcompr(const unmanaged_string& in, int level) +{ + return zlib_gzcompr(in, level); +} +std::string crypto::zlib::gzuncompr(const unmanaged_string& in) +{ + return zlib_gzuncompr(in); +} + +std::vector crypto::zlib::abi::compress(const unmanaged_string& in, int level) +{ + return zlib_compress>(in, level); +} +std::vector crypto::zlib::abi::uncompress(const unmanaged_string& in) +{ + return zlib_uncompress>(in); +} +std::vector crypto::zlib::abi::deflate(const unmanaged_string& in, int level) +{ + return zlib_deflate>(in, level); +} +std::vector crypto::zlib::abi::inflate(const unmanaged_string& in) +{ + return zlib_inflate>(in); +} +std::vector crypto::zlib::abi::gzcompr(const unmanaged_string& in, int level) +{ + return zlib_gzcompr>(in, level); +} +std::vector crypto::zlib::abi::gzuncompr(const unmanaged_string& in) +{ + return zlib_gzuncompr>(in); +} + +std::string crypto::hash::md5(const unmanaged_string& plaintext) +{ + char ciphertext[32]; + + md5chars(plaintext.c_str(), plaintext.length(), ciphertext); + + return std::string(ciphertext, sizeof(ciphertext)); +} + +std::string crypto::hash::md5raw(const unmanaged_string& plaintext) +{ + char ciphertext[16]; + + ::md5(plaintext.c_str(), plaintext.length(), ciphertext); + + return std::string(ciphertext, sizeof(ciphertext)); +} + +std::string crypto::hash::fmd5(const char* filename) +{ + FILE* fp = fopen(filename, "rb"); + // std::ifstream fin(filename, std::ios_base::binary); + if (fp == NULL) + { + // std::cout << "Transmission Client: open failed!\n"; + return ""; + } + + //fin.seekg(0, std::ios_base::end); + //std::streamsize bytes_left = fin.tellg(); // filesize initialized + //fin.seekg(0, std::ios_base::beg); + auto bytes_left = fsutil::get_file_size(fp); + + char buffer[HASH_FILE_BUFF_SIZE]; + + md5_state_t state; + + char hash[16] = { 0 }; + std::string result(32, '\0'); + + md5_init(&state); + + while (bytes_left > 0) { + auto n = (std::min)((std::streamsize)sizeof(buffer), (std::streamsize)bytes_left); + // fin.read(buffer, bytes_read); + auto bytes_read = fread(buffer, 1, n, fp); + md5_append(&state, (unsigned char*)buffer, bytes_read); + bytes_left -= bytes_read; + } + + fclose(fp); + md5_finish(&state, (unsigned char*)hash); + + hexs2chars(hash, sizeof(hash), &result.front(), result.size()); + + return std::move(result); +} + +#if defined(MD6_SUPPORT) +std::string crypto::hash::md6(const std::string& plaintext) +{ + // char ciphertext[128]; + std::string result(128, '\0'); + + ::md6chars(plaintext.c_str(), plaintext.length(), &result.front(), 64); + + return std::move(result); // std::string(ciphertext, sizeof(ciphertext)); +} + +std::string crypto::hash::md6raw(const std::string& plaintext) +{ + std::string result(64, '\0'); + + ::md6(plaintext.c_str(), plaintext.length(), &result.front(), 64); + + return std::move(result); +} + + + +std::string crypto::hash::fmd6(const char* filename, int hashByteLen) +{ + std::ifstream fin; + fin.open(filename, std::ios_base::binary); + if (!fin.is_open()) + { + // std::cout << "Transmission Client: open failed!\n"; + return ""; + } + + fin.seekg(0, std::ios_base::end); + std::streamsize bytes_left = fin.tellg(); // filesize initialized + fin.seekg(0, std::ios_base::beg); + + char buffer[HASH_FILE_BUFF_SIZE]; + + md6_state state; + + if (hashByteLen > 64) + hashByteLen = 64; + // int hashByteLen = 64; + + // assert(hashByteLen <= 64); + + char hash[64] = { 0 }; + std::string result(hashByteLen << 1, '\0'); + + md6_init(&state, hashByteLen << 3); + + while (bytes_left > 0) { + int bytes_read = (std::min)((std::streamsize)sizeof(buffer), bytes_left); + fin.read(buffer, bytes_read); + md6_update(&state, (unsigned char*)buffer, bytes_read << 3); + bytes_left -= bytes_read; + } + + fin.close(); + md6_final(&state, (unsigned char*)hash); + + hexs2chars(hash, hashByteLen, &result.front(), result.size()); + + return std::move(result); +} +#endif /* MD6_SUPPORT */ + +std::string crypto::http::b64dec(const unmanaged_string& ciphertext) +{ + std::string plaintext( ciphertext.length(), '\0' ); + + base64_decodestate state; + base64_init_decodestate(&state); + int r1 = base64_decode_block(ciphertext.c_str(), ciphertext.length(), &plaintext.front(), &state); + + plaintext.resize(r1); + return std::move(plaintext); +} + +std::string crypto::http::b64enc(const unmanaged_string& plaintext) +{ + std::string ciphertext( (plaintext.length() * 2), '\0' ); + char* wrptr = &ciphertext.front(); + base64_encodestate state; + base64_init_encodestate(&state); + int r1 = base64_encode_block(plaintext.c_str(), plaintext.length(), wrptr, &state); + int r2 = base64_encode_blockend(wrptr + r1, &state); + + ciphertext.resize(r1 + r2); + return std::move(ciphertext); +} + +std::string crypto::http::urlencode(const unmanaged_string& input) +{ + std::string output; + for( size_t ix = 0; ix < input.size(); ix++ ) + { + uint8_t buf[4]; + memset( buf, 0, 4 ); + if( isalnum( (uint8_t)input[ix] ) ) + { + buf[0] = input[ix]; + } + //else if ( isspace( (BYTE)sIn[ix] ) ) + //{ + // buf[0] = '+'; + //} + else + { + buf[0] = '%'; + buf[1] = ::hex2uchr( (uint8_t)input[ix] >> 4 ); + buf[2] = ::hex2uchr( (uint8_t)input[ix] % 16); + } + output += (char *)buf; + } + return std::move(output); +}; + +std::string crypto::http::urldecode(const unmanaged_string& ciphertext) +{ + std::string result = ""; + + for( size_t ix = 0; ix < ciphertext.size(); ix++ ) + { + uint8_t ch = 0; + if(ciphertext[ix]=='%') + { + ch = (::uchr2hex(ciphertext[ix+1])<<4); + ch |= ::uchr2hex(ciphertext[ix+2]); + ix += 2; + } + else if(ciphertext[ix] == '+') + { + ch = ' '; + } + else + { + ch = ciphertext[ix]; + } + result += (char)ch; + } + + return std::move(result); +} +// appended zlib_inflate func +managed_cstring crypto::zlib::abi::_inflate(const unmanaged_string& compr) +{ // inflate + int err; + Bytef buffer[128]; + z_stream d_stream; /* decompression stream */ + + // strcpy((char*)buffer, "garbage"); + + d_stream.zalloc = nullptr; + d_stream.zfree = nullptr; + d_stream.opaque = (voidpf)0; + + d_stream.next_in = (Bytef*)compr.c_str(); + d_stream.avail_in = compr.size(); + d_stream.next_out = buffer; + d_stream.avail_out = sizeof(buffer); + managed_cstring output; + err = inflateInit(&d_stream); + if (err != Z_OK) // TODO: log somthing + return std::move(output); + // CHECK_ERR(err, "inflateInit"); + + output.reserve(compr.size() << 2); + for (;;) + { + err = inflate(&d_stream, Z_NO_FLUSH); + + if (err == Z_STREAM_END) + { + output.cappend((const char*)buffer, sizeof(buffer) - d_stream.avail_out); + break; + } + + switch (err) + { + case Z_NEED_DICT: + err = Z_DATA_ERROR; + case Z_DATA_ERROR: + case Z_MEM_ERROR: + goto _L_end; + } + + // not enough memory ? + if (err != Z_STREAM_END) + { + // *out = (unsigned char*)realloc(*out, bufferSize * BUFFER_INC_FACTOR); + output.cappend((const char*)buffer, sizeof(buffer)); + + d_stream.next_out = buffer; + d_stream.avail_out = sizeof(buffer); + } + } + +_L_end: + inflateEnd(&d_stream); + if (err != Z_STREAM_END) + { + output.clear(); + } + + return std::move(output); +} diff --git a/src/crypto_wrapper.h b/src/crypto_wrapper.h new file mode 100644 index 0000000000000000000000000000000000000000..c1d270af9e1e673c8e2fc89edbb6906d049df98d --- /dev/null +++ b/src/crypto_wrapper.h @@ -0,0 +1,233 @@ +#ifndef _CRYPTO_WRAPPER_H_ +#define _CRYPTO_WRAPPER_H_ +#include +#include +#include +#include "unreal_string.h" +#include "crypto_utils.h" + +using namespace purelib; + +namespace crypto { + + /// IV is defined intrin + namespace aes { + + /// padding + namespace privacy { + template + struct padding_spec + { + template + inline static size_t perform(_BYTE_SEQ_CONT& plaintext, size_t blocksize = AES_BLOCK_SIZE) { return detail::padding::PKCS7(plaintext, blocksize); } + }; + + template<> + struct padding_spec < PaddingMode::ISO10126 > + { + template + inline static size_t perform(_BYTE_SEQ_CONT& plaintext, size_t blocksize = AES_BLOCK_SIZE) { return detail::padding::ISO10126(plaintext, blocksize); } + }; + + template<> + struct padding_spec < PaddingMode::ANSIX923 > + { + template + inline static size_t perform(_BYTE_SEQ_CONT& plaintext, size_t blocksize = AES_BLOCK_SIZE) { return detail::padding::ANSIX923(plaintext, blocksize); } + }; + + template<> + struct padding_spec < PaddingMode::Zeros > + { + template + inline static size_t perform(_BYTE_SEQ_CONT& plaintext, size_t blocksize = AES_BLOCK_SIZE) { return detail::padding::ZEROS(plaintext, blocksize); } + }; + + template<> + struct padding_spec < PaddingMode::None > + { + template + inline static size_t perform(_BYTE_SEQ_CONT& plaintext, size_t blocksize = AES_BLOCK_SIZE) { return 0; } + }; + + template + struct mode_spec + { + static void encrypt(const void* in, size_t inlen, + char* out, size_t outlen, const void* private_key, int keybits = 256) + { + detail::cbc_encrypt(in, inlen, out, outlen, private_key, keybits); + } + + static void decrypt(const void* in, size_t inlen, + void* out, size_t& outlen, const void* private_key, int keybits = 256) + { + detail::cbc_decrypt(in, inlen, out, outlen, private_key, keybits); + } + }; + + template<> + struct mode_spec < CipherMode::ECB > + { + static void encrypt(const void* in, size_t inlen, + void* out, size_t outlen, const void* private_key, int keybits = 256) + { + detail::ecb_encrypt(in, inlen, out, outlen, private_key, keybits); + } + + static void decrypt(const void* in, size_t inlen, + void* out, size_t& outlen, const void* private_key, int keybits = 256) + { + detail::ecb_decrypt(in, inlen, out, outlen, private_key, keybits); + } + }; + }; + + /// encrypt decrypt APIs + + template + inline _BYTE_SEQ_CONT encrypt(const _BYTE_SEQ_CONT& in, const void* key = DEFAULT_KEY, int keybits = 256) + { + auto out = in; + privacy::padding_spec::perform(out); + + privacy::mode_spec::encrypt(out.data(), + out.size(), + &out.front(), + out.size(), + key, + keybits); + return std::move(out); + } + + template + inline _BYTE_SEQ_CONT decrypt(const _BYTE_SEQ_CONT& in, const void* key = DEFAULT_KEY, int keybits = 256) + { + size_t outlen = in.size(); + _BYTE_SEQ_CONT out(outlen, 0x0); + privacy::mode_spec::decrypt(in.data(), + in.size(), + &out.front(), + outlen, + key, + keybits); + out.resize(outlen); + return std::move(out); + } + + template + inline _BYTE_SEQ_CONT encrypt(_BYTE_SEQ_CONT&& in, const void* key = DEFAULT_KEY, int keybits = 256) + { + privacy::padding_spec::perform(in); + + privacy::mode_spec::encrypt(in.data(), + in.size(), + &in.front(), + in.size(), + key, + keybits); + return std::move(in); + } + + template + inline _BYTE_SEQ_CONT decrypt(_BYTE_SEQ_CONT&& in, const void* key = DEFAULT_KEY, int keybits = 256) + { + size_t outlen = in.size(); + privacy::mode_spec::decrypt(in.data(), + in.size(), + &in.front(), + outlen, + key, + keybits); + in.resize(outlen); + return std::move(in); + } + + /// wrappers, strongly encrypt, low speed; false: use ECB: fast speed, light-weighted encrypt + namespace overlapped { + + template + inline void encrypt(_BYTE_SEQ_CONT& inout, const void* key = DEFAULT_KEY, int keybits = 256, size_t offset = 0) + { + privacy::padding_spec::perform(inout); + + privacy::mode_spec::encrypt(inout.data() + offset, + inout.size() - offset, + &inout.front() + offset, + inout.size() - offset, + key, + keybits); + } + + template + inline void decrypt(_BYTE_SEQ_CONT& inout, const void* key = DEFAULT_KEY, int keybits = 256, size_t offset = 0) + { + size_t outlen = 0; + privacy::mode_spec::decrypt(inout.data() + offset, + inout.size() - offset, + &inout.front() + offset, + outlen, + key, + keybits); + + inout.resize(outlen); + } + } + + } /* end of namespace crypto::aes */ + + namespace zlib { + /* + ** level values: + ** Z_NO_COMPRESSION 0 + ** Z_BEST_SPEED 1 + ** Z_BEST_COMPRESSION 9 + ** Z_DEFAULT_COMPRESSION (-1) + ** + */ + std::string compress(const unmanaged_string& in, int level = -1); // zlib 1.2.8 Z_DEFAULT_COMPRESSION is -1 + std::string uncompress(const unmanaged_string& in); + + std::string deflate(const unmanaged_string& in, int level = -1); // zlib 1.2.8 Z_DEFAULT_COMPRESSION is -1 + std::string inflate(const unmanaged_string& in); + + std::string gzcompr(const unmanaged_string& in, int level = -1); + std::string gzuncompr(const unmanaged_string& in); + + namespace abi { + std::vector compress(const unmanaged_string& in, int level = -1); // zlib 1.2.8 Z_DEFAULT_COMPRESSION is -1 + std::vector uncompress(const unmanaged_string& in); + + std::vector deflate(const unmanaged_string& in, int level = -1); // zlib 1.2.8 Z_DEFAULT_COMPRESSION is -1 + std::vector inflate(const unmanaged_string& in); + + std::vector gzcompr(const unmanaged_string& in, int level = -1); + std::vector gzuncompr(const unmanaged_string& in); + + managed_cstring _inflate(const unmanaged_string& in); + }; + }; + + namespace http { + std::string b64dec(const unmanaged_string& ciphertext); + + std::string b64enc(const unmanaged_string& plaintext); + + std::string urldecode(const unmanaged_string& ciphertext); + + std::string urlencode(const unmanaged_string& input); + }; + + namespace hash { + std::string md5(const unmanaged_string& string); + std::string md5raw(const unmanaged_string& string); + std::string fmd5(const char* filename); + + std::string md6(const std::string& data); // small data + std::string md6raw(const std::string& data); + std::string fmd6(const char* filename, int hashByteLen = 64); + }; +}; + +#endif + diff --git a/src/deadline_timer.cpp b/src/deadline_timer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..10afaaf22c2c1fc8d7ef5138c23338c54fad800c --- /dev/null +++ b/src/deadline_timer.cpp @@ -0,0 +1,54 @@ +////////////////////////////////////////////////////////////////////////////////////////// +// A cross platform socket APIs, support ios & android & wp8 & window store universal app +// version: 2.2 +////////////////////////////////////////////////////////////////////////////////////////// +/* +The MIT License (MIT) + +Copyright (c) 2012-2016 halx99 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#ifndef _XXSOCKET_DEADLINE_TIMER_IPP_ +#define _XXSOCKET_DEADLINE_TIMER_IPP_ +#include "deadline_timer.h" +#include "async_tcp_client.h" + +namespace purelib { +namespace inet { +deadline_timer::~deadline_timer() +{ +} + +void deadline_timer::async_wait(const std::function& callback) +{ + this->callback_ = callback; + tcpcli->schedule_timer(this); +} + +void deadline_timer::cancel() +{ + tcpcli->cancel_timer(this); +} + +} +} +#endif + diff --git a/src/deadline_timer.h b/src/deadline_timer.h new file mode 100644 index 0000000000000000000000000000000000000000..93349d2784daba0c42eeefa45c604667e6154217 --- /dev/null +++ b/src/deadline_timer.h @@ -0,0 +1,89 @@ +////////////////////////////////////////////////////////////////////////////////////////// +// A cross platform socket APIs, support ios & android & wp8 & window store universal app +// version: 2.2 +////////////////////////////////////////////////////////////////////////////////////////// +/* +The MIT License (MIT) + +Copyright (c) 2012-2016 halx99 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#ifndef _XXSOCKET_DEADLINE_TIMER_H_ +#define _XXSOCKET_DEADLINE_TIMER_H_ +#include +#include + +#if defined(_MSC_VER) && _MSC_VER < 1900 +typedef std::chrono::time_point compatible_timepoint_t; +#else +typedef std::chrono::time_point compatible_timepoint_t; +#endif + +namespace purelib +{ +namespace inet { +class deadline_timer { +public: + ~deadline_timer(); + deadline_timer() + { + } + deadline_timer(const std::chrono::microseconds& duration, bool loop = false) + { + expires_from_now(duration, loop); + } + + void expires_from_now(const std::chrono::microseconds& duration, bool loop = false) + { + this->duration_ = duration; + this->loop_ = loop; + + expire_time_ = std::chrono::steady_clock::now() + this->duration_; + } + + void expires_from_now() + { + expire_time_ = std::chrono::steady_clock::now() + this->duration_; + } + + void async_wait(const std::function& callback); + + void cancel(); + + bool expired() const + { + return wait_duration().count() <= 0; + } + + std::chrono::microseconds wait_duration() const + { + return std::chrono::duration_cast(expire_time_ - std::chrono::steady_clock::now()); + } + + bool loop_; + std::chrono::microseconds duration_; + compatible_timepoint_t expire_time_; + std::function callback_; +}; +} +} + +#endif diff --git a/src/eventfd_select_interrupter.hpp b/src/eventfd_select_interrupter.hpp new file mode 100644 index 0000000000000000000000000000000000000000..88fa9798cd35e7126cdc7e38f3f6e24c89c1408f --- /dev/null +++ b/src/eventfd_select_interrupter.hpp @@ -0,0 +1,71 @@ +// +// detail/eventfd_select_interrupter.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2008 Roelof Naude (roelof.naude at gmail dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef XXSOCKET_EVENTFD_SELECT_INTERRUPTER_HPP +#define XXSOCKET_EVENTFD_SELECT_INTERRUPTER_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +namespace purelib { +namespace inet { + +class eventfd_select_interrupter +{ +public: + // Constructor. + _XXSOCKET_INLINE eventfd_select_interrupter(); + + // Destructor. + _XXSOCKET_INLINE ~eventfd_select_interrupter(); + + // Recreate the interrupter's descriptors. Used after a fork. + _XXSOCKET_INLINE void recreate(); + + // Interrupt the select call. + _XXSOCKET_INLINE void interrupt(); + + // Reset the select interrupt. Returns true if the call was interrupted. + _XXSOCKET_INLINE bool reset(); + + // Get the read descriptor to be passed to select. + int read_descriptor() const + { + return read_descriptor_; + } + +private: + // Open the descriptors. Throws on error. + _XXSOCKET_INLINE void open_descriptors(); + + // Close the descriptors. + _XXSOCKET_INLINE void close_descriptors(); + + // The read end of a connection used to interrupt the select call. This file + // descriptor is passed to select such that when it is time to stop, a single + // 64bit value will be written on the other end of the connection and this + // descriptor will become readable. + int read_descriptor_; + + // The write end of a connection used to interrupt the select call. A single + // 64bit non-zero value may be written to this to wake up the select which is + // waiting for the other end to become readable. This descriptor will only + // differ from the read descriptor when a pipe is used. + int write_descriptor_; +}; + +} // namespace inet +} // namespace purelib + +# include "eventfd_select_interrupter.ipp" + +#endif // BOOST_ASIO_DETAIL_EVENTFD_SELECT_INTERRUPTER_HPP diff --git a/src/eventfd_select_interrupter.ipp b/src/eventfd_select_interrupter.ipp new file mode 100644 index 0000000000000000000000000000000000000000..104520068e735d7fc6aa091c97b4e7fa4040b551 --- /dev/null +++ b/src/eventfd_select_interrupter.ipp @@ -0,0 +1,157 @@ +// +// detail/impl/eventfd_select_interrupter.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2008 Roelof Naude (roelof.naude at gmail dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef XXSOCKET_IMPL_EVENTFD_SELECT_INTERRUPTER_IPP +#define XXSOCKET_IMPL_EVENTFD_SELECT_INTERRUPTER_IPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include +#include +#include +#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 8 +# include +#else // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8 +# include +#endif // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8 +//#include +//#include +//#include +//#include +// +//#include + +namespace purelib { +namespace inet { + +eventfd_select_interrupter::eventfd_select_interrupter() +{ + open_descriptors(); +} + +void eventfd_select_interrupter::open_descriptors() +{ +#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 8 + write_descriptor_ = read_descriptor_ = syscall(__NR_eventfd, 0); + if (read_descriptor_ != -1) + { + ::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK); + ::fcntl(read_descriptor_, F_SETFD, FD_CLOEXEC); + } +#else // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8 +# if defined(EFD_CLOEXEC) && defined(EFD_NONBLOCK) + write_descriptor_ = read_descriptor_ = + ::eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK); +# else // defined(EFD_CLOEXEC) && defined(EFD_NONBLOCK) + errno = EINVAL; + write_descriptor_ = read_descriptor_ = -1; +# endif // defined(EFD_CLOEXEC) && defined(EFD_NONBLOCK) + if (read_descriptor_ == -1 && errno == EINVAL) + { + write_descriptor_ = read_descriptor_ = ::eventfd(0, 0); + if (read_descriptor_ != -1) + { + ::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK); + ::fcntl(read_descriptor_, F_SETFD, FD_CLOEXEC); + } + } +#endif // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8 + + if (read_descriptor_ == -1) + { + int pipe_fds[2]; + if (pipe(pipe_fds) == 0) + { + read_descriptor_ = pipe_fds[0]; + ::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK); + ::fcntl(read_descriptor_, F_SETFD, FD_CLOEXEC); + write_descriptor_ = pipe_fds[1]; + ::fcntl(write_descriptor_, F_SETFL, O_NONBLOCK); + ::fcntl(write_descriptor_, F_SETFD, FD_CLOEXEC); + } + else + { + /*boost::system::error_code ec(errno, + boost::asio::error::get_system_category()); + boost::asio::detail::throw_error(ec, "eventfd_select_interrupter");*/ + } + } +} + +eventfd_select_interrupter::~eventfd_select_interrupter() +{ + close_descriptors(); +} + +void eventfd_select_interrupter::close_descriptors() +{ + if (write_descriptor_ != -1 && write_descriptor_ != read_descriptor_) + ::close(write_descriptor_); + if (read_descriptor_ != -1) + ::close(read_descriptor_); +} + +void eventfd_select_interrupter::recreate() +{ + close_descriptors(); + + write_descriptor_ = -1; + read_descriptor_ = -1; + + open_descriptors(); +} + +void eventfd_select_interrupter::interrupt() +{ + uint64_t counter(1UL); + int result = ::write(write_descriptor_, &counter, sizeof(uint64_t)); + (void)result; +} + +bool eventfd_select_interrupter::reset() +{ + if (write_descriptor_ == read_descriptor_) + { + for (;;) + { + // Only perform one read. The kernel maintains an atomic counter. + uint64_t counter(0); + errno = 0; + int bytes_read = ::read(read_descriptor_, &counter, sizeof(uint64_t)); + if (bytes_read < 0 && errno == EINTR) + continue; + bool was_interrupted = (bytes_read > 0); + return was_interrupted; + } + } + else + { + for (;;) + { + // Clear all data from the pipe. + char data[1024]; + int bytes_read = ::read(read_descriptor_, data, sizeof(data)); + if (bytes_read < 0 && errno == EINTR) + continue; + bool was_interrupted = (bytes_read > 0); + while (bytes_read == sizeof(data)) + bytes_read = ::read(read_descriptor_, data, sizeof(data)); + return was_interrupted; + } + } +} + +} // namespace inet +} // namespace purelib + +#endif // BOOST_ASIO_DETAIL_IMPL_EVENTFD_SELECT_INTERRUPTER_IPP diff --git a/src/fastest_csv_parser.h b/src/fastest_csv_parser.h index f5fcf63b56c7837c12d25ec705b3e73efe187223..4c6f3cfaf2fbf9fd28f438bf14dca00ddc62d841 100644 --- a/src/fastest_csv_parser.h +++ b/src/fastest_csv_parser.h @@ -4,23 +4,24 @@ #include #include #include -#include "purelib/utils/xxfsutility.h" +#include "xxfsutility.h" class fastest_csv_parser { public: + // test & usage for csv parse void parse_csv(const char* filename) { std::string buffer = fsutil::read_file_data(filename); - - if(buffer.empty()) + + if (buffer.empty()) return; const char* newl = buffer.c_str(); do { std::vector record; - newl = csv_parse_line(newl, [&record](const char* v_start, const char* v_end){ + newl = csv_parse_line(newl, [&record](const char* v_start, const char* v_end) { std::string temp = std::string(v_start, v_end); record.push_back(std::move(temp)); }); @@ -32,8 +33,8 @@ public: /* * op prototype: op(const char* v_start, const char* v_end) */ - template inline - static const char* csv_parse_line(const char* s, _Fty op) + template inline + static const char* xsv_pase_line(const char* s, _Fty op) { enum { normal, // new field @@ -45,13 +46,13 @@ public: const char* _Start = s; // the start of every string const char* _Ptr = s; // source string iterator - int skipCRLF = 1; + int _LLF = 1; // skip CRLF _L_loop: { switch (*_Ptr) { - case ',': + case _Delim: switch (state) { case normal: if (_Start <= _Ptr) @@ -64,7 +65,6 @@ public: break; default:; // explicit_string_start, do nothing } - break; case '\"': if (state == normal) { @@ -79,7 +79,7 @@ public: break; case '\r': - skipCRLF = 2; + _LLF = 2; case '\n': case '\0': if (_Start <= _Ptr && state == normal) { @@ -93,7 +93,16 @@ public: } _L_end: - return _Ptr + skipCRLF; // pointer to next line or after of null-termainted-charactor + return _Ptr + _LLF; // pointer to next line or after of null-termainted-charactor + } + + /* + * op prototype: op(const char* v_start, const char* v_end) + */ + template inline + static const char* csv_parse_line(const char* s, _Fty op) + { + return xsv_pase_line<',', _Fty>(s, op); } }; diff --git a/src/ibinarystream.h b/src/ibinarystream.h index a7326ca96f9480adc92c777de200f56793deb935..ed690a94d8aa616b06703279f999b1b9edbbe9ce 100644 --- a/src/ibinarystream.h +++ b/src/ibinarystream.h @@ -19,7 +19,9 @@ public: ibinarystream& operator=(ibinarystream&& right) = delete; template - int read_i(_Nty& ov); + void read_i(_Nty& ov); + void read_i(float& ov); + void read_i(double& ov); int read_v(std::string& ov); int read_v(void* ov, int len); @@ -39,10 +41,22 @@ protected: }; template -inline int ibinarystream::read_i(_Nty & ov) +inline void ibinarystream::read_i(_Nty & ov) { ov = purelib::endian::ntohv(*((_Nty*)(ptr_))); - return consume(sizeof(_Nty)); + consume(sizeof(_Nty)); +} + +inline void ibinarystream::read_i(float& ov) +{ + ov = ntohf(*((uint32_t*)(ptr_))); + consume(sizeof(ov)); +} + +inline void ibinarystream::read_i(double& ov) +{ + ov = ntohd(*((uint64_t*)(ptr_))); + consume(sizeof(uint64_t)); } #endif diff --git a/src/libb64.cpp b/src/libb64.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e50aa62784e34f14f6ef1f24149db41de316326c --- /dev/null +++ b/src/libb64.cpp @@ -0,0 +1,187 @@ +/* + This is part of the libb64 project, and has been placed in the public domain. + For details, see http://sourceforge.net/projects/libb64 + */ + +#include "libb64.h" + +int base64_decode_value(char value_in) +{ + static const char decoding[] = {62,-1,-1,-1,63,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-2,-1,-1,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51}; + static const char decoding_size = sizeof(decoding); + value_in -= 43; + if (value_in < 0 || value_in > decoding_size) return -1; + return decoding[(int)value_in]; +} + +void base64_init_decodestate(base64_decodestate* state_in) +{ + state_in->step = step_a; + state_in->plainchar = 0; +} + +int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in) +{ + const char* codechar = code_in; + char* plainchar = plaintext_out; + char fragment; + + *plainchar = state_in->plainchar; + + switch (state_in->step) + { + while (1) + { + case step_a: + do { + if (codechar == code_in+length_in) + { + state_in->step = step_a; + state_in->plainchar = *plainchar; + return plainchar - plaintext_out; + } + fragment = (char)base64_decode_value(*codechar++); + } while (fragment < 0); + *plainchar = (fragment & 0x03f) << 2; + case step_b: + do { + if (codechar == code_in+length_in) + { + state_in->step = step_b; + state_in->plainchar = *plainchar; + return plainchar - plaintext_out; + } + fragment = (char)base64_decode_value(*codechar++); + } while (fragment < 0); + *plainchar++ |= (fragment & 0x030) >> 4; + *plainchar = (fragment & 0x00f) << 4; + case step_c: + do { + if (codechar == code_in+length_in) + { + state_in->step = step_c; + state_in->plainchar = *plainchar; + return plainchar - plaintext_out; + } + fragment = (char)base64_decode_value(*codechar++); + } while (fragment < 0); + *plainchar++ |= (fragment & 0x03c) >> 2; + *plainchar = (fragment & 0x003) << 6; + case step_d: + do { + if (codechar == code_in+length_in) + { + state_in->step = step_d; + state_in->plainchar = *plainchar; + return plainchar - plaintext_out; + } + fragment = (char)base64_decode_value(*codechar++); + } while (fragment < 0); + *plainchar++ |= (fragment & 0x03f); + } + } + /* control should not reach here */ + return plainchar - plaintext_out; +} + + +const int CHARS_PER_LINE = 0x7fffffff; // modify by xxseekerj: orignal value: 72 + +void base64_init_encodestate(base64_encodestate* state_in) +{ + state_in->step = step_A; + state_in->result = 0; + state_in->stepcount = 0; +} + +char base64_encode_value(char value_in) +{ + static const char* encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + if (value_in > 63) return '='; + return encoding[(int)value_in]; +} + +int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in) +{ + const char* plainchar = plaintext_in; + const char* const plaintextend = plaintext_in + length_in; + char* codechar = code_out; + char result; + char fragment; + + result = state_in->result; + + switch (state_in->step) + { + while (1) + { + case step_A: + if (plainchar == plaintextend) + { + state_in->result = result; + state_in->step = step_A; + return codechar - code_out; + } + fragment = *plainchar++; + result = (fragment & 0x0fc) >> 2; + *codechar++ = base64_encode_value(result); + result = (fragment & 0x003) << 4; + case step_B: + if (plainchar == plaintextend) + { + state_in->result = result; + state_in->step = step_B; + return codechar - code_out; + } + fragment = *plainchar++; + result |= (fragment & 0x0f0) >> 4; + *codechar++ = base64_encode_value(result); + result = (fragment & 0x00f) << 2; + case step_C: + if (plainchar == plaintextend) + { + state_in->result = result; + state_in->step = step_C; + return codechar - code_out; + } + fragment = *plainchar++; + result |= (fragment & 0x0c0) >> 6; + *codechar++ = base64_encode_value(result); + result = (fragment & 0x03f) >> 0; + *codechar++ = base64_encode_value(result); + + ++(state_in->stepcount); + if (state_in->stepcount == CHARS_PER_LINE/4) + { + *codechar++ = '\n'; + state_in->stepcount = 0; + } + } + } + /* control should not reach here */ + return codechar - code_out; +} + +int base64_encode_blockend(char* code_out, base64_encodestate* state_in) +{ + char* codechar = code_out; + + switch (state_in->step) + { + case step_B: + *codechar++ = base64_encode_value(state_in->result); + *codechar++ = '='; + *codechar++ = '='; + break; + case step_C: + *codechar++ = base64_encode_value(state_in->result); + *codechar++ = '='; + break; + case step_A: + break; + } + // *codechar++ = '\n'; commit by xxseekerj + + return codechar - code_out; +} + diff --git a/src/libb64.h b/src/libb64.h new file mode 100644 index 0000000000000000000000000000000000000000..e91575b64ce778cebda8102da2af19ee59738214 --- /dev/null +++ b/src/libb64.h @@ -0,0 +1,49 @@ + +/* + This is part of the libb64 project, and has been placed in the public domain. + For details, see http://sourceforge.net/projects/libb64 + */ + +#ifndef __LIBB64_H_ +#define __LIBB64_H_ +//#ifdef __cplusplus +//extern "C" { +//#endif +typedef enum +{ + step_a, step_b, step_c, step_d +} base64_decodestep; + +typedef struct +{ + base64_decodestep step; + char plainchar; +} base64_decodestate; + +void base64_init_decodestate(base64_decodestate* state_in); +int base64_decode_value(char value_in); +int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in); + + +typedef enum +{ + step_A, step_B, step_C +} base64_encodestep; + +typedef struct +{ + base64_encodestep step; + char result; + int stepcount; +} base64_encodestate; + +void base64_init_encodestate(base64_encodestate* state_in); +char base64_encode_value(char value_in); +int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in); +int base64_encode_blockend(char* code_out, base64_encodestate* state_in); +//#ifdef __cplusplus +//} +//#endif + +#endif /* __LIBB64_H_ */ + diff --git a/src/nsconv.h b/src/nsconv.h new file mode 100644 index 0000000000000000000000000000000000000000..84549f04380465ee06ebe48e1be6a667fc5d8134 --- /dev/null +++ b/src/nsconv.h @@ -0,0 +1,816 @@ +// nsconv standard header, contain several methods for typecast between numeric and string +#ifndef _NSCONV_H_ +#define _NSCONV_H_ +#include +#include +#ifdef _WIN32 +# include +#include +#endif +#include "politedef.h" +#include +#include +#include +#include +#include + +#include + +// #include "unreal_string.h" + +namespace purelib { + +namespace nsconv {}; +namespace nsc = nsconv; + +namespace nsconv { + +typedef std::ios_base& (*ios_flag)(std::ios_base&); + +template inline + std::basic_string<_Elem, std::char_traits<_Elem>, _Alloc> to_xstring(const _Nty& numeral, ios_flag radix = std::dec) +{ + std::basic_stringstream<_Elem, std::char_traits<_Elem>, _Alloc> swaper; + swaper.precision(16); + swaper << radix << numeral; + + return swaper.str(); +} + +template inline + std::basic_string<_Elem, std::char_traits<_Elem>, _Alloc>& to_xstring(const _Nty& numeral, std::basic_string<_Elem, std::char_traits<_Elem>, _Alloc>& output, ios_flag radix = std::dec) +{ + std::basic_stringstream<_Elem, std::char_traits<_Elem>, _Alloc> swaper; + swaper.precision(16); + swaper << radix << numeral; + swaper >> output; + + return output; +} + +// convert numeric[char/short/int/long/long long/float/double] to string[std::string/std::wstring]. +template inline +std::string to_string(const _Nty& numeral, ios_flag radix = std::dec) +{ + std::stringstream swaper; + swaper.precision(16); + swaper << radix << numeral; + + return swaper.str(); +} + +template inline +std::string& to_string(const _Nty& numeral, std::string& text, ios_flag radix = std::dec) +{ + std::stringstream swaper; + swaper.precision(16); + swaper << radix << numeral; + swaper >> text; + + return text; +} +template inline +std::wstring to_wstring(const _Nty& numeral, ios_flag radix = std::dec) +{ + std::wstringstream swaper; + swaper.precision(16); + swaper << radix << numeral; + + return swaper.str(); +} + +template inline +std::wstring& to_wstring(const _Nty& numeral, std::wstring& text, ios_flag radix = std::dec) +{ + std::wstringstream swaper; + swaper.precision(16); + swaper << radix << numeral; + + swaper >> text; + + return text; +} +/*@method@ to_string @method@*/ + + +// convert string[std::string/std::wstring] to numeric[char/short/int/long/long long/float/double]. +template inline +_Nty to_numeric(const std::basic_string<_Elem>& text, ios_flag radix = std::dec) +{ + _Nty numeral = _Nty(); + std::basic_stringstream<_Elem> swaper; + swaper.precision(16); + swaper << radix << text; + swaper >> numeral; + + return numeral; +} + +template inline +_Nty& to_numeric(const std::basic_string<_Elem>& text, _Nty& numeral, ios_flag radix = std::dec) +{ + std::basic_stringstream<_Elem> swaper; + swaper.precision(16); + swaper << radix << text; + swaper >> numeral; + + return numeral; +} /*@method@ to_numeric @method@*/ + +// convert string[NTCS] to numeric[char/short/int/long/long long/float/double]. +template inline +_Nty to_numeric(const _Elem* text, ios_flag radix = std::dec) +{ + _Nty numeral = _Nty(); + std::basic_stringstream<_Elem> swaper; + + swaper.precision(16); + swaper << radix << text; + swaper >> numeral; + + return numeral; +} + +template inline +_Nty& to_numeric(const _Elem* text, _Nty& numeral, ios_flag radix = std::dec) +{ + std::basic_stringstream<_Elem> swaper; + swaper.precision(16); + swaper << radix << text; + swaper >> numeral; + + return numeral; +} /*@method@ to_numeric @method@*/ + +inline +bool _Is_visible_char(int _Char) +{ + return (_Char > 0x20 && _Char < 0x7F); +} + +template inline +size_t strtrim(_Elem* _Str) +{ + if(NULL == _Str || !*_Str) { + return 0; + } + + _Elem* _Ptr = _Str - 1; + + while( !_Is_visible_char(*(++_Ptr)) && *_Ptr ) ; + + _Elem* _First = _Ptr; + _Elem* _Last = _Ptr; + if(*_Ptr) { + while(*(++_Ptr)) + { + if(_Is_visible_char(*_Ptr)) { + _Last = _Ptr; + } + } + } + + size_t _Count = _Last - _First + 1; + if(_Ptr != _Str) { + ::memmove(_Str, _First, _Count); + _Str[_Count] = '\0'; + } + + return _Count; +} + +template inline +int strtrim(_Elem* _Str, int _StrLen) +{ + if(NULL == _Str || !*_Str) { + return 0; + } + _Elem* _Ptr = _Str - 1; + + while( !_Is_visible_char(*(++_Ptr)) && --_StrLen ) ; + + if(_StrLen > 0) { + while( !_Is_visible_char(_Ptr[_StrLen - 1]) ) --_StrLen ; + _Ptr[_StrLen] = (_Elem)'\0'; + } + + if(_Ptr != _Str) { + ::memmove(_Str, _Ptr, _StrLen); + _Str[_StrLen] = (_Elem)'\0'; + } + + return _StrLen; +} + +template +std::basic_string<_Elem>& strtrim(std::basic_string<_Elem>& _String) +{ + _String.resize(strtrim(const_cast<_Elem*>(_String.c_str()), _String.length())); + return _String; +} + +#ifdef __cxx11 +template inline +std::basic_string<_Elem>& strtrim(std::basic_string<_Elem>&& _String) +{ + return strtrim(_String); +} +#endif + +/* +* nsc::split API (override+6) +* op prototype: [](const char* start, const char* end){} +*/ +template inline +void split(const _Elem* s, const _Elem delim, const _Fty& op) +{ + const _Elem* _Start = s; // the start of every string + const _Elem* _Ptr = s; // source string iterator + while( *_Ptr != '\0' ) + { + if(delim == *_Ptr/* && _Ptr != _Start*/) + { + if (_Ptr != _Start) + op(_Start, _Ptr); + _Start = _Ptr + 1; + } + ++_Ptr; + } + if(_Start != _Ptr) { + op(_Start, _Ptr); + } +} + +template inline +void split(const _Elem* s, size_t slen, const _Elem* delims, size_t dlen, const _Fty& op) +{ + const _Elem* _Start = s; // the start of every string + const _Elem* _Ptr = s; // source string iterator + size_t _Lend = dlen; + while ((_Ptr = strstr(_Ptr, delims)) != nullptr) + { + if (_Ptr > _Start) + { + op(_Start, _Ptr); + } + _Start = _Ptr + _Lend; + _Ptr += _Lend; + } + if (*_Start) { + op(_Start, s + slen); + } +} + +template inline +void split(const _Elem* s, const _Elem* delims, const _Fty& op) +{ + split(s, strlen(s), delims, strlen(delims), op); +} + +template inline +void split(const std::basic_string<_Elem>& s, const _Elem* delims, const _Fty& op) +{ + size_t start = 0; + size_t last = s.find_first_of(delims, start); + while (last != std::basic_string<_Elem>::npos) + { + if (last > start) + op(&s[start], &s[last - start]); + last = s.find_first_of(delims, start = last + 1); + } + if (start < s.size()) + { + op(&s(start), &s.back()); + } +} + +template inline +std::vector> split(const _Elem* s, const _Elem delim) +{ + std::vector > output; + nsc::split(s, delim, [&output](const _Elem* start, const _Elem* end)->void{ + output.push_back(std::basic_string<_Elem>(start, end)); + }); + return std::move(output); +} + +template inline +std::vector> split(const _Elem* s, const _Elem* delims) +{ + std::vector > output; + nsc::split(s, delims, [&output](const _Elem* start, const _Elem* end)->void{ + output.push_back(std::basic_string<_Elem>(start, end)); + }); + return std::move(output); +} + +template inline +void _Dir_split(_Elem* s, const _Fty& op) // will convert '\\' to '/' +{ + _Elem* _Start = s; // the start of every string + _Elem* _Ptr = s; // source string iterator + while (*_Ptr != '\0') + { + if ('\\' == *_Ptr || '/' == *_Ptr) + { + if (_Ptr != _Start) { + auto _Ch = *_Ptr; + *_Ptr = '\0'; + bool should_brk = op(s); +#if defined(_WIN32) + *_Ptr = '\\'; +#else // For unix linux like system. + *_Ptr = '/'; +#endif + if (should_brk) + return; + } + _Start = _Ptr + 1; + } + ++_Ptr; + } + if (_Start != _Ptr) { + op(s); + } +} + +template inline +void dir_split(std::basic_string<_Elem>& s, const _Fty& op) // will convert '\\' to '/' +{ + _Dir_split(&s.front(), op); +} + +template inline +void dir_split(std::basic_string<_Elem>&& s, const _Fty& op) // will convert '\\' to '/' +{ + dir_split(s, op); +} + +inline +std::string& replace(std::string& string, const std::string& replaced_key, const std::string& replacing_key) +{ + std::string::size_type pos = 0; + while( (pos = string.find(replaced_key, pos)) != std::string::npos ) + { + (void)string.replace(pos, replaced_key.length(), replacing_key); + pos += replacing_key.length(); + } + return string; +} + +inline +std::string& replace(std::string&& string, const std::string& replaced_key, const std::string& replacing_key) +{ + return replace(string, replaced_key, replacing_key); +} + +inline +std::string::size_type replace_once(std::string& string, const std::string& replaced_key, const std::string& replacing_key) +{ + std::string::size_type pos = 0; + if( (pos = string.find(replaced_key, pos)) != std::string::npos ) + { + (void)string.replace(pos, replaced_key.length(), replacing_key); + return pos; + } + return std::string::npos; +} + +inline +std::string rsubstr(const std::string& string, size_t off) +{ + if(string.length() >= off) + { + return string.substr(string.length() - off); + } + return ""; +} + +template inline +void strtoupper(_Elem* source) +{ + while( *source != '\0' ) + { + *source = toupper(*source); + ++source; + } +} + +template inline +void strtolower(_Elem* source) +{ + while( *source != '\0' ) + { + *source = tolower(*source); + ++source; + } +} + +/// charstring2hexstring +/// hexstring2hexbinary +static char char2hex(const char ch) +{ + return isdigit(ch) ? (ch - '0') : (tolower(ch) - 'a' + 10); +} + +static char hex2char(const char hex) +{ + return ( hex < 0xa ? (hex + '0') : (hex + 'a' - 10) ); +} + +// translate charstring/binarystream to hexstring +static std::string bin2hex(const std::string& binary /*charstring also regard as binary in C/C++*/, int delim = -1, bool prefix = false) +{ + char low; + char high; + size_t len = binary.length(); + + bool delim_needed = _Is_visible_char(delim) || delim == ' '; + + std::string result; + result.reserve((len << 1) + delim_needed ? len : 0 + prefix ? (len << 1) : 0); + + + for(size_t i = 0; i < len; ++i) + { + auto ch = binary[i]; + high = (ch >> 4) & 0x0f; + low = ch & 0x0f; + if (prefix) { + result.push_back('0'); + result.push_back('x'); + } + + auto hic = hex2char(high); + auto lic = hex2char(low); + result.push_back(hic); + result.push_back(lic); + if (delim_needed) + { + result.push_back(delim); + } + } + + return std::move(result); +} + +// translate hexstring to binary +static std::string hex2bin(const std::string& hexstring, int delim = -1, bool prefix = false) +{ + char low; + char high; + size_t len = hexstring.length(); + + std::string result; + result.reserve((len >> 1) + 1); + + enum { + skip_prefix, + take_low, + take_high, + } state; + + auto init_state = skip_prefix; + if (!prefix) + init_state = take_low; + + state = init_state; + for(size_t i = 0; i < len; ++i) + { + // skip delim + if (delim != -1) + if(hexstring[i] == delim) + continue; + + switch(state) { + case take_low: + low = char2hex(hexstring[i]); + state = take_high; + break; + case take_high: + high = char2hex(hexstring[i]); + result.push_back( ( (uint8_t)low << 4 | (uint8_t)high ) ); + state = init_state; + break; + } + } + + return result.size() >= 2 ? std::move(result) : ""; +} + +static std::string bin2dec(const std::string& binary /*charstring also regard as binary in C/C++*/, int delim = -1) +{ + /*char low; + char high;*/ + size_t len = binary.length(); + + bool delim_needed = _Is_visible_char(delim) || delim == ' '; + + std::string result; + result.reserve((len << 1) + delim_needed ? len : 0); + + char temp[8]; + for (size_t i = 0; i < len; ++i) + { + auto ch = binary[i]; + sprintf(temp, "%d", (char)ch); + result.append(temp); + if (delim_needed) + { + result.push_back(delim); + } + } + + return std::move(result); +} + +template inline + void reverse_sb(_Elem* _Str, size_t _Count) +{ + size_t start = 0; + size_t last = _Count - 1; + while( start != last ) + { + if(_Str[start] != _Str[last]) + { + std::swap(_Str[start], _Str[last]); + } + ++start, --last; + } +} + +static +std::tuple parse2i(const std::string& strValue, const char delim) +{ + char* endptr = nullptr; + int value1 = (int)strtol(strValue.c_str(), &endptr, 10); + if (*endptr == delim) + { + return std::make_tuple(value1, (int)strtol(endptr + 1, nullptr, 10)); + } + + return std::make_tuple(value1, 0); +} + +static +std::tuple parse3i(const std::string& strValue, const char delim) +{ + char* endptr = nullptr; + int value1 = (int)strtol(strValue.c_str(), &endptr, 10); + if (*endptr == delim) + { + int value2 = (int)strtol(endptr + 1, &endptr, 10); + if (*endptr == delim) + { + return std::make_tuple(value1, value2, (int)strtol(endptr + 1, nullptr, 10)); + } + return std::make_tuple(value1, value2, 0); + } + + return std::make_tuple(value1, 0, 0); +} + +static +std::tuple parse2f(const std::string& strValue, const char delim) +{ + char* endptr = nullptr; + float value1 = strtof(strValue.c_str(), &endptr); + if (*endptr == delim) + { + return std::make_tuple(value1, strtof(endptr + 1, nullptr)); + } + + return std::make_tuple(value1, .0f); +} + +static +std::tuple parse3f(const std::string& strValue, const char delim) +{ + char* endptr = nullptr; + float value1 = strtof(strValue.c_str(), &endptr); + if (*endptr == delim) + { + float value2 = strtof(endptr + 1, &endptr); + if (*endptr == delim) + { + return std::make_tuple(value1, value2, strtof(endptr + 1, nullptr)); + } + return std::make_tuple(value1, value2, .0f); + } + + return std::make_tuple(value1, .0f, .0f); +} + +static +std::tuple parse4i(const std::string& strValue, const char delim) +{ + char* endptr = nullptr; + auto value1 = (int)strtol(strValue.c_str(), &endptr, 10); + if (*endptr == delim) + { + auto value2 = (int)strtol(endptr + 1, &endptr, 10); + if (*endptr == delim) + { + auto value3 = (int)strtol(endptr + 1, &endptr, 10); + if (*endptr == delim) + { + return std::make_tuple(value1, value2, value3, (int)strtol(endptr + 1, nullptr, 10)); + } + return std::make_tuple(value1, value2, value3, 0); + } + return std::make_tuple(value1, value2, 0, 0); + } + + return std::make_tuple(value1, 0, 0, 0); +} + +static +std::tuple parse4f(const std::string& strValue, const char delim) +{ + char* endptr = nullptr; + float value1 = strtof(strValue.c_str(), &endptr); + if (*endptr == delim) + { + float value2 = strtof(endptr + 1, &endptr); + if (*endptr == delim) + { + float value3 = strtof(endptr + 1, &endptr); + if (*endptr == delim) + { + return std::make_tuple(value1, value2, value3, strtof(endptr + 1, nullptr)); + } + return std::make_tuple(value1, value2, value3, .0f); + } + return std::make_tuple(value1, value2, .0f, .0f); + } + + return std::make_tuple(value1, .0f, .0f, .0f); +} + +#ifdef _WIN32 + +enum code_page { + code_page_acp = CP_ACP, + code_page_utf8 = CP_UTF8 +}; + +inline std::string transcode(const wchar_t* wcb, code_page cp = code_page_acp) +{ + int buffersize = WideCharToMultiByte(cp, 0, wcb, -1, NULL, 0, NULL, NULL); + std::string buffer(buffersize, '\0'); + WideCharToMultiByte(cp, 0, wcb, -1, &buffer.front(), buffersize, NULL, NULL); + buffer.resize(buffersize - 1); + return std::move(buffer); +} + +inline std::string transcode(const std::wstring& wcb, code_page cp = code_page_acp) +{ + int buffersize = WideCharToMultiByte(cp, 0, wcb.c_str(), -1, NULL, 0, NULL, NULL); + std::string buffer(buffersize, '\0'); + WideCharToMultiByte(cp, 0, wcb.c_str(), -1, &buffer.front(), buffersize, NULL, NULL); + buffer.resize(buffersize - 1); + return std::move(buffer); +} + +inline std::wstring transcode(const char* mcb, code_page cp = code_page_acp) +{ + int buffersize = MultiByteToWideChar(cp, 0, mcb, -1, NULL, 0); + std::wstring buffer(buffersize, '\0'); + MultiByteToWideChar(cp, 0, mcb, -1, &buffer.front(), buffersize); + buffer.resize(buffersize - 1); + return std::move(buffer); +} + +inline std::wstring transcode(const std::string& mcb, code_page cp = code_page_acp) +{ + int buffersize = MultiByteToWideChar(cp, 0, mcb.c_str(), -1, NULL, 0); + std::wstring buffer(buffersize, '\0'); + MultiByteToWideChar(cp, 0, mcb.c_str(), -1, &buffer.front(), buffersize); + buffer.resize(buffersize - 1); + return std::move(buffer); +} + +inline std::string to_utf8(const char* ascii_text) +{ + return transcode(transcode(ascii_text).c_str(), code_page_utf8); +} + +inline std::string to_ascii(const char* utf8_text) +{ + return transcode(transcode(utf8_text, code_page_utf8).c_str()); +} + +#ifndef WINRT + +/* utils GUID +** +*/ +#include "xxbswap.h" + +#define GUID_BUF_SIZE ( sizeof(_GUID) * 2 + sizeof(void*) ) + +inline void create_guid(LPTSTR outs) +{ + _GUID guid; + CoCreateGuid(&guid); + + wsprintf(outs, TEXT("%08X-%04X-%04X-%04X-%04X%08X"), + guid.Data1, + guid.Data2, + guid.Data3, + __bswap16(*(reinterpret_cast(guid.Data4))), + __bswap16(*(reinterpret_cast(guid.Data4 + 2))), + __bswap32(*(reinterpret_cast(guid.Data4 + 4))) + ); +} + +inline void create_guid_v2(LPTSTR outs) +{ + _GUID guid; + CoCreateGuid(&guid); + + wsprintf(outs, TEXT("%08X%04X%04X%016I64X"), + guid.Data1, + guid.Data2, + guid.Data3, + __bswap64(*(reinterpret_cast(guid.Data4))) + ); +} + + +template inline +std::basic_string<_Elem> create_guid(void) +{ + std::basic_stringstream<_Elem> swaper; + + _GUID g; + CoCreateGuid(&g); + + swaper << std::hex + << std::setw(8) << std::setfill(_Elem('0')) << g.Data1 + << _Elem('-') + << std::setw(4) << std::setfill(_Elem('0')) << g.Data2 + << _Elem('-') + << std::setw(4) << std::setfill(_Elem('0')) << g.Data3 + << _Elem('-') + << std::setw(4) << std::setfill(_Elem('0')) << ntohs(*reinterpret_cast(g.Data4)) + << _Elem('-') + << std::setw(4) << std::setfill(_Elem('0')) << ntohs(*reinterpret_cast(g.Data4 + 2)) + << std::setw(8) << std::setfill(_Elem('0')) << ntohl(*reinterpret_cast(g.Data4 + 4)); + + return swaper.str(); +} + +template inline +std::basic_string<_Elem> create_guid_v2(void) +{ + std::basic_stringstream<_Elem> swaper; + + _GUID g; + CoCreateGuid(&g); + + swaper << std::hex + << std::setw(8) << std::setfill(_Elem('0')) << g.Data1 + << _Elem('-') + << std::setw(4) << std::setfill(_Elem('0')) << g.Data2 + << _Elem('-') + << std::setw(4) << std::setfill(_Elem('0')) << g.Data3 + << _Elem('-') + << std::setw(16) << std::setfill(_Elem('0')) << __bswap64(*reinterpret_cast(g.Data4)); + + return swaper.str(); +} + +// just like a md5 32 byte string. +template inline +std::basic_string<_Elem> create_guid_v3(void) +{ + std::basic_stringstream<_Elem> swaper; + + _GUID g; + CoCreateGuid(&g); + + swaper << std::hex + << std::setw(8) << std::setfill(_Elem('0')) << g.Data1 + << std::setw(4) << std::setfill(_Elem('0')) << g.Data2 + << std::setw(4) << std::setfill(_Elem('0')) << g.Data3 + << std::setw(16) << std::setfill(_Elem('0')) << __bswap64(*reinterpret_cast(g.Data4)); + + return swaper.str(); +} + +#endif + +#endif + + +}; // namespace: purelib::nsconv + +}; // namespace: purelib + +#endif /* _NSCONV_ */ +/* +* Copyright (c) 2012-2014 by xseekerj ALL RIGHTS RESERVED. +* Consult your license regarding permissions and restrictions. +**/ + diff --git a/src/oslib.h b/src/oslib.h index a32f1d162cce3a40392ac56894de17163abbd26d..fd5165786672dcbedfbf1ae47165689ca9752583 100644 --- a/src/oslib.h +++ b/src/oslib.h @@ -33,7 +33,7 @@ typedef unsigned long DWORD; # define __threadlocal __declspec(thread) # define thread_native_type DWORD -# define this_thread GetCurrentThreadId +// # define this_thread GetCurrentThreadId #elif defined(__linux) diff --git a/src/pipe_select_interrupter.hpp b/src/pipe_select_interrupter.hpp new file mode 100644 index 0000000000000000000000000000000000000000..cbf31789050b023c3827e19c8c9dda4371b00473 --- /dev/null +++ b/src/pipe_select_interrupter.hpp @@ -0,0 +1,87 @@ +// +// detail/pipe_select_interrupter.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef XXSOCKET_PIPE_SELECT_INTERRUPTER_HPP +#define XXSOCKET_PIPE_SELECT_INTERRUPTER_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +//#include +// +//#if !defined(BOOST_ASIO_WINDOWS) +//#if !defined(BOOST_ASIO_WINDOWS_RUNTIME) +//#if !defined(__CYGWIN__) +//#if !defined(__SYMBIAN32__) +//#if !defined(BOOST_ASIO_HAS_EVENTFD) +// +//#include + +namespace purelib { +namespace inet { + +class pipe_select_interrupter +{ +public: + // Constructor. + _XXSOCKET_INLINE pipe_select_interrupter(); + + // Destructor. + _XXSOCKET_INLINE ~pipe_select_interrupter(); + + // Recreate the interrupter's descriptors. Used after a fork. + _XXSOCKET_INLINE void recreate(); + + // Interrupt the select call. + _XXSOCKET_INLINE void interrupt(); + + // Reset the select interrupt. Returns true if the call was interrupted. + _XXSOCKET_INLINE bool reset(); + + // Get the read descriptor to be passed to select. + int read_descriptor() const + { + return read_descriptor_; + } + +private: + // Open the descriptors. Throws on error. + _XXSOCKET_INLINE void open_descriptors(); + + // Close the descriptors. + _XXSOCKET_INLINE void close_descriptors(); + + // The read end of a connection used to interrupt the select call. This file + // descriptor is passed to select such that when it is time to stop, a single + // byte will be written on the other end of the connection and this + // descriptor will become readable. + int read_descriptor_; + + // The write end of a connection used to interrupt the select call. A single + // byte may be written to this to wake up the select which is waiting for the + // other end to become readable. + int write_descriptor_; +}; + +} // namespace inet +} // namespace purelib + + +# include "pipe_select_interrupter.ipp" + + +//#endif // !defined(BOOST_ASIO_HAS_EVENTFD) +//#endif // !defined(__SYMBIAN32__) +//#endif // !defined(__CYGWIN__) +//#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME) +//#endif // !defined(BOOST_ASIO_WINDOWS) + +#endif // BOOST_ASIO_DETAIL_PIPE_SELECT_INTERRUPTER_HPP diff --git a/src/pipe_select_interrupter.ipp b/src/pipe_select_interrupter.ipp new file mode 100644 index 0000000000000000000000000000000000000000..5e2a1ef1dc58d35edfa1fb58fa377dede98faf7a --- /dev/null +++ b/src/pipe_select_interrupter.ipp @@ -0,0 +1,103 @@ +// +// detail/impl/pipe_select_interrupter.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef XXSOCKET_IMPL_PIPE_SELECT_INTERRUPTER_IPP +#define XXSOCKET_IMPL_PIPE_SELECT_INTERRUPTER_IPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include +#include +#include +#include + +namespace purelib { +namespace inet { +pipe_select_interrupter::pipe_select_interrupter() +{ + open_descriptors(); +} + +void pipe_select_interrupter::open_descriptors() +{ + int pipe_fds[2]; + if (pipe(pipe_fds) == 0) + { + read_descriptor_ = pipe_fds[0]; + ::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK); + write_descriptor_ = pipe_fds[1]; + ::fcntl(write_descriptor_, F_SETFL, O_NONBLOCK); + +#if defined(FD_CLOEXEC) + ::fcntl(read_descriptor_, F_SETFD, FD_CLOEXEC); + ::fcntl(write_descriptor_, F_SETFD, FD_CLOEXEC); +#endif // defined(FD_CLOEXEC) + } + else + { + /*boost::system::error_code ec(errno, + boost::asio::error::get_system_category()); + boost::asio::detail::throw_error(ec, "pipe_select_interrupter");*/ + } +} + +pipe_select_interrupter::~pipe_select_interrupter() +{ + close_descriptors(); +} + +void pipe_select_interrupter::close_descriptors() +{ + if (read_descriptor_ != -1) + ::close(read_descriptor_); + if (write_descriptor_ != -1) + ::close(write_descriptor_); +} + +void pipe_select_interrupter::recreate() +{ + close_descriptors(); + + write_descriptor_ = -1; + read_descriptor_ = -1; + + open_descriptors(); +} + +void pipe_select_interrupter::interrupt() +{ + char byte = 0; + auto result = ::write(write_descriptor_, &byte, 1); + (void)result; +} + +bool pipe_select_interrupter::reset() +{ + for (;;) + { + char data[1024]; + auto bytes_read = ::read(read_descriptor_, data, sizeof(data)); + if (bytes_read < 0 && errno == EINTR) + continue; + bool was_interrupted = (bytes_read > 0); + while (bytes_read == sizeof(data)) + bytes_read = ::read(read_descriptor_, data, sizeof(data)); + return was_interrupted; + } +} + +} // namespace inet +} // namespace purelib + + + +#endif // BOOST_ASIO_DETAIL_IMPL_PIPE_SELECT_INTERRUPTER_IPP diff --git a/src/politedef.h b/src/politedef.h index 412af00b31e42849fc2e04753a42d230e5dea178..b77f05baf7668633f64029ffa797aaa73528517a 100644 --- a/src/politedef.h +++ b/src/politedef.h @@ -10,7 +10,7 @@ #define _POLITEDEF_H_ #ifndef _POLITE_VERSION -#define _POLITE_VERSION "1.0.1" +#define _POLITE_VERSION "1.0.16" #endif #if defined(_MSC_VER) @@ -58,7 +58,7 @@ typedef unsigned long u_long; typedef long long llong; typedef unsigned long long u_llong; -#if /*defined(__cxx11) || */defined(__GNUC__) +#if defined(__cxx11) || defined(__GNUC__) #include #else typedef signed __int8 int8_t; @@ -247,6 +247,14 @@ namespace polite = ::purelib; #define _HAS_STD_THREAD 1 #endif +#if !defined(__WORDSIZE) +#if defined(_M_X64) || defined(_WIN64) || defined(__LP64__) || defined(_LP64) || defined(__x86_64) +#define __WORDSIZE 64 +#else +#define __WORDSIZE 32 +#endif +#endif + #endif /* _POLITEDEF_H_ */ /* * Copyright (c) 2012-2014 by X.D. Guo ALL RIGHTS RESERVED. diff --git a/src/select_interrupter.hpp b/src/select_interrupter.hpp new file mode 100644 index 0000000000000000000000000000000000000000..d2d08eea71b2bab39441786e1d947f9da5254571 --- /dev/null +++ b/src/select_interrupter.hpp @@ -0,0 +1,45 @@ +// +// detail/select_interrupter.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef XXSOCKET_SELECT_INTERRUPTER_HPP +#define XXSOCKET_SELECT_INTERRUPTER_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + + +#if !defined(_XXSOCKET_INLINE) +#define _XXSOCKET_INLINE inline +#endif + +#if defined(_WIN32) +# include "socket_select_interrupter.hpp" +#elif defined(__linux__) +# include "eventfd_select_interrupter.hpp" +#else +# include "pipe_select_interrupter.hpp" +#endif + +namespace purelib { +namespace inet { + +#if defined(_WIN32) +typedef socket_select_interrupter select_interrupter; +#elif defined(__linux__) +typedef eventfd_select_interrupter select_interrupter; +#else +typedef pipe_select_interrupter select_interrupter; +#endif + +} // namespace inet +} // namespace purelib + +#endif // BOOST_ASIO_DETAIL_SELECT_INTERRUPTER_HPP diff --git a/src/socket_select_interrupter.hpp b/src/socket_select_interrupter.hpp new file mode 100644 index 0000000000000000000000000000000000000000..44762706feb866ce8a853db5696354afaf4ae439 --- /dev/null +++ b/src/socket_select_interrupter.hpp @@ -0,0 +1,87 @@ +////////////////////////////////////////////////////////////////////////////////////////// +// A cross platform socket APIs, support ios & android & wp8 & window store universal app +// version: 2.2 +////////////////////////////////////////////////////////////////////////////////////////// +/* +The MIT License (MIT) + +Copyright (c) 2012-2016 halx99 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +#ifndef _XXSOCKET_SELECT_INTERRUPTER_HPP_ +#define _XXSOCKET_SELECT_INTERRUPTER_HPP_ +#include "xxsocket.h" +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + + +namespace purelib { +namespace inet { + + class socket_select_interrupter +{ +public: + // Constructor. + _XXSOCKET_INLINE socket_select_interrupter(); + + // Destructor. + _XXSOCKET_INLINE ~socket_select_interrupter(); + + // Recreate the interrupter's descriptors. Used after a fork. + _XXSOCKET_INLINE void recreate(); + + // Interrupt the select call. + _XXSOCKET_INLINE void interrupt(); + + // Reset the select interrupt. Returns true if the call was interrupted. + _XXSOCKET_INLINE bool reset(); + + // Get the read descriptor to be passed to select. + socket_native_type read_descriptor() const + { + return read_descriptor_; + } + +private: + // Open the descriptors. Throws on error. + _XXSOCKET_INLINE void open_descriptors(); + + // Close the descriptors. + _XXSOCKET_INLINE void close_descriptors(); + + // The read end of a connection used to interrupt the select call. This file + // descriptor is passed to select such that when it is time to stop, a single + // byte will be written on the other end of the connection and this + // descriptor will become readable. + socket_native_type read_descriptor_; + + // The write end of a connection used to interrupt the select call. A single + // byte may be written to this to wake up the select which is waiting for the + // other end to become readable. + socket_native_type write_descriptor_; +}; + +} // namespace inet +} // namespace purelib + +#include "socket_select_interrupter.ipp" + +#endif // BOOST_ASIO_DETAIL_SOCKET_SELECT_INTERRUPTER_HPP diff --git a/src/socket_select_interrupter.ipp b/src/socket_select_interrupter.ipp new file mode 100644 index 0000000000000000000000000000000000000000..6ee1bdd92947b63ef9ed2114fbe328d81c031d5b --- /dev/null +++ b/src/socket_select_interrupter.ipp @@ -0,0 +1,119 @@ +////////////////////////////////////////////////////////////////////////////////////////// +// A cross platform socket APIs, support ios & android & wp8 & window store universal app +// version: 2.2 +////////////////////////////////////////////////////////////////////////////////////////// +/* +The MIT License (MIT) + +Copyright (c) 2012-2016 halx99 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +#ifndef _IMPL_XXSOCKET_SELECT_INTERRUPTER_IPP_ +#define _IMPL_XXSOCKET_SELECT_INTERRUPTER_IPP_ + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) +// #include "select_interrupter.h" + +namespace purelib { +namespace inet { + +socket_select_interrupter::socket_select_interrupter() +{ + open_descriptors(); +} + +void socket_select_interrupter::open_descriptors() +{ + xxsocket acceptor(AF_INET, SOCK_STREAM, IPPROTO_TCP); + acceptor.set_optval(SOL_SOCKET, SO_REUSEADDR, 1); + + int error = 0; + ip::endpoint ep("127.0.0.1", 0); + + error = acceptor.bind(ep); + ep = acceptor.local_endpoint(); + // Some broken firewalls on Windows will intermittently cause getsockname to + // return 0.0.0.0 when the socket is actually bound to 127.0.0.1. We + // explicitly specify the target address here to work around this problem. + // addr.sin_addr.s_addr = socket_ops::host_to_network_long(INADDR_LOOPBACK); + // cp.address("127.0.0.1"); + ep.address("127.0.0.1"); + error = acceptor.listen(); + + xxsocket client(AF_INET, SOCK_STREAM, IPPROTO_TCP); + error = client.connect(ep); + + auto server = acceptor.accept(); + + client.set_nonblocking(true); + client.set_optval(IPPROTO_TCP, TCP_NODELAY, 1); + + server.set_nonblocking(true); + client.set_optval(IPPROTO_TCP, TCP_NODELAY, 1); + + read_descriptor_ = server.release(); + write_descriptor_ = client.release(); +} + +socket_select_interrupter::~socket_select_interrupter() +{ + close_descriptors(); +} + +void socket_select_interrupter::close_descriptors() +{ + if (read_descriptor_ != invalid_socket) + ::closesocket(read_descriptor_); + + if (write_descriptor_ != invalid_socket) + ::closesocket(write_descriptor_); +} + +void socket_select_interrupter::recreate() +{ + close_descriptors(); + + write_descriptor_ = invalid_socket; + read_descriptor_ = invalid_socket; + + open_descriptors(); +} + +void socket_select_interrupter::interrupt() +{ + xxsocket::send_i(write_descriptor_, "\0", 1); +} + +bool socket_select_interrupter::reset() +{ + char buffer[1024]; + int bytes_read = xxsocket::recv_i(read_descriptor_, buffer, sizeof(buffer), 0); + bool was_interrupted = (bytes_read > 0); + while (bytes_read == sizeof(buffer)) + bytes_read = xxsocket::recv_i(read_descriptor_, buffer, sizeof(buffer), 0); + return was_interrupted; +} + +} // namespace inet +} // namespace purelib + +#endif diff --git a/src/timestamp.h b/src/timestamp.h new file mode 100644 index 0000000000000000000000000000000000000000..db23ec7f1efbc5cbb5b47b1d19aa06dc4a51c479 --- /dev/null +++ b/src/timestamp.h @@ -0,0 +1,88 @@ +#ifndef _RANDOM_H_ +#define _RANDOM_H_ +//#define __random__(min,max) rand() % ((max) - (min)) + (min) + +#include +#include +#ifdef _WIN32 +#include +#else +#include +#define sprintf_s snprintf +#endif +#include +#include + + +inline const char* ctimestamp(void) +{ + static char tms[32]; +#ifdef _WIN32 + SYSTEMTIME t; + GetLocalTime(&t); + sprintf_s(tms, sizeof(tms), "[%d-%02d-%02d %02d:%02d:%02d.%03d]", t.wYear, t.wMonth, t.wDay, t.wHour, t.wMinute, t.wSecond, t.wMilliseconds); +#else + struct timeval tv; + gettimeofday(&tv, NULL); + struct tm* t = localtime(&tv.tv_sec); + sprintf_s(tms, sizeof(tms), "[%d-%02d-%02d %02d:%02d:%02d.%03d]", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, (int)tv.tv_usec / 1000); +#endif + return tms; +} + +/*static +std::string timestamp(void) +{ +#ifdef _WIN32 + SYSTEMTIME t; + GetLocalTime(&t); + std::ostringstream oss; + oss << "[" + << std::setw(2) << std::setfill('0') << t.wHour << ":" + << std::setw(2) << std::setfill('0') << t.wMinute << ":" + << std::setw(2) << std::setfill('0') << t.wSecond << "." + << std::setw(3) << std::setfill('0') << t.wMilliseconds + << "]"; + return oss.str(); +#else + timeval tv; + gettimeofday(&tv, NULL); + tm* t = localtime(&tv.tv_sec); + std::ostringstream oss; + oss << "[" + << std::setw(2) << std::setfill('0') << t->tm_hour << ":" + << std::setw(2) << std::setfill('0') << t->tm_min << ":" + << std::setw(2) << std::setfill('0') << t->tm_sec << "." + << std::setw(3) << std::setfill('0') << tv.tv_usec / 1000 + << "]"; + return oss.str(); +#endif +} +*/ + +//static void dump_hex(const char* prompt, const char* hex, int len, FILE* fp = stdout, int line_feed = 16) +//{ +// fprintf(fp, prompt); +// for(int i = 0; i < len; ++i) +// { +// if( i + 1 != len) { +// if( (i + 1) % line_feed != 0 ) { +// fprintf(fp, "%02x ", (unsigned int)hex[i]); +// } +// else { +// fprintf(fp, "%02x\n", (unsigned int)hex[i]); +// } +// } +// else { +// fprintf(fp, "%02x\n", (unsigned int)hex[i]); +// } +// } +//} + +#endif +/* +* Copyright (c) 2012-2013 by X.D. Guo ALL RIGHTS RESERVED. +* Consult your license regarding permissions and restrictions. +**/ + + diff --git a/src/unreal_string.h b/src/unreal_string.h new file mode 100644 index 0000000000000000000000000000000000000000..640accfd275016fc41392d63564bee19b7929160 --- /dev/null +++ b/src/unreal_string.h @@ -0,0 +1,1175 @@ +// unreal_string.h +#ifndef _UNREAL_STRING_H_ +#define _UNREAL_STRING_H_ + +#include +#include +#include +#include +#include "xxfree.h" + +namespace purelib { + using namespace gc; + +#define ULS_ELEM_SHIFT (sizeof(_Elem) >> 1) + + namespace native_utils { + template inline + size_t strlen(const _Elem* _Str) + { + const _Elem* pos = _Str; + + while (*(pos++)); + + return (pos - _Str - 1); + } + + template inline + void reversesb(_Elem* _Str) + { + size_t start = 0; + size_t last = strlen(_Str) - 1; + while (start != last) + { + if (_Str[start] != _Str[last]) + { + std::swap(_Str[start], _Str[last]); + } + ++start, --last; + } + } + + template inline + void reversesb(_Elem* _Str, size_t _Count) + { + size_t start = 0; + size_t last = _Count - 1; + while (start != last) + { + if (_Str[start] != _Str[last]) + { + std::swap(_Str[start], _Str[last]); + } + ++start, --last; + } + } + + template inline + void reversesba(_Elem(&_Str)[_Size]) + { + size_t start = 0; + size_t last = _Size - 2; + while (start != last) + { + // const char* type = typeid(_Str[start]).name(); + if (_Str[start] != _Str[last]) + { + std::swap(_Str[start], _Str[last]); + } + ++start, --last; + } + } + + template inline + int strcmp(const _Elem* _Str1, const _Elem* _Str2) + { + int ret = 0; + + while (!(ret = (unsigned int)*_Str1 - (unsigned int)*_Str2) && *_Str2) + ++_Str1, ++_Str2; + + return ret; + } + + template inline + _Elem* strcpy(_Elem* _DstStr, const _Elem* _SrcStr) + { + _Elem* _Rp = _DstStr; + + while ((*(_DstStr++) = *(_SrcStr++))); + + return _Rp; + } + template inline + _Elem* strcpy_s(_Elem* _DstStr, size_t _DstSize, const _Elem* _SrcStr) + { + if (_DstSize <= (strlen(_SrcStr))) + { + return 0; + } + + return strcpy(_DstStr, _SrcStr); + } + template inline + _Elem* strcpy_s(_Elem(&_DstStr)[_DstSize], const _Elem* _SrcStr) + { + return strcpy_s(_DstStr, _DstSize, _SrcStr); + } + + + template inline + _Elem* strncpy(_Elem* _DstStr, const _Elem* _SrcStr, size_t _Count) + { + _Elem* _Rp = _DstStr; + + while (((_DstStr - _Rp) < _Count) && + (*(_DstStr++) = *(_SrcStr++))); + + *_DstStr = (_Elem)0; + + return _Rp; + } + + template inline + _Elem* strncpy_s(_Elem* _DstStr, size_t _DstSize, const _Elem* _SrcStr, size_t _Count) + { + if (_DstSize <= _Count) + { + return 0; + } + + return strncpy(_DstStr, _SrcStr, _Count); + } + + template inline + _Elem* strncpy_s(_Elem(&_DstStr)[_DstSize], const _Elem* _SrcStr, size_t _Count) + { + return strncpy_s(_DstStr, _DstSize, _SrcStr, _Count); + } + + template inline + _Elem* strcat(_Elem* _DstStr, const _Elem* _SrcStr) + { + _Elem * _Rp = _DstStr; + + while (*(_DstStr)) ++_DstStr; + + while ((*(_DstStr++) = *(_SrcStr++))); + + return (_Rp); + } + + template inline + _Elem* strcat_s(_Elem* _DstStr, size_t _DstSize, const _Elem* _SrcStr) + { + if (_DstSize <= strlen(_DstStr) + strlen(_SrcStr)) + { + return 0; + } + + return strcat(_DstStr, _SrcStr); + } + + template inline + _Elem* strcat_s(_Elem* _DstStr, const _Elem* _SrcStr) + { + return strcat_s(_DstStr, _DstSize, _SrcStr); + } + + template inline + _Elem toupper(_Elem ch) + { + return ((ch >= 'a' && ch <= 'z') ? (ch - 0x20) : ch); + } + + template inline + _Elem tolower(_Elem ch) + { + return ((ch >= 'A' && ch <= 'Z') ? (ch + 0x20) : ch); + } + + template inline + void strtoupper_noncopy(_Elem* _DstStr) + { + while (*_DstStr != 0x0) + { + if (*_DstStr >= 'a' && *_DstStr <= 'z') + { + *_DstStr -= 0x20; + } + ++_DstStr; + } + } + + template inline + void strtolower_noncopy(_Elem* _DstStr) + { + while (*_DstStr != 0x0) + { + if (*_DstStr >= 'A' && *_DstStr <= 'Z') + { + *_DstStr += 0x20; + } + ++_DstStr; + } + } + + }; + + // TEMPLATE CLASS unreal_string forward declare + template > + class unreal_string; + + typedef unreal_string > managed_cstring; + typedef unreal_string > managed_wcstring; + typedef unreal_string > managed_string; + typedef unreal_string > managed_wstring; + typedef unreal_string > unmanaged_string; + typedef unreal_string > unmanaged_wstring; + + template + class unreal_string + { + typedef unreal_string<_Elem, _Cleaner> _Myt; + + public: + unreal_string(void) + { + _Tidy(); + } + + unreal_string(const _Elem* _Ptr) + { + _Tidy(); + this->assign(_Ptr); + } + + template + unreal_string(const _Elem(&_Ptr)[_Size]) + { + _Tidy(); + this->assign(_Ptr, _Size); + } + + unreal_string(const _Elem* _Ptr, size_t _Length) + { + _Tidy(); + this->assign(_Ptr, _Length); + } + + unreal_string(const _Elem* _First, const _Elem* _Last) + { + _Tidy(); + this->assign(_First, _Last); + } + + unreal_string(_Elem* _Ptr) + { + _Tidy(); + this->assign(_Ptr); + } + + unreal_string(_Elem* _Ptr, size_t _Length) + { + _Tidy(); + this->assign(_Ptr, _Length); + } + + unreal_string(_Elem* _First, _Elem* _Last) + { + _Tidy(); + this->assign(_First, _Last); + } + + unreal_string(const std::basic_string<_Elem>& _Right) + { + _Tidy(); + this->assign(_Right); + } + +#if defined(_AFX) || defined(__CSTRINGT_H__) + +#if defined(_AFXDLL) +#define _ULS_StrTraitMFC StrTraitMFC_DLL +#else +#define _ULS_StrTraitMFC StrTraitMFC +#endif + + unreal_string(const ATL::CStringT<_Elem, _ULS_StrTraitMFC< _Elem >>& _Right) + { + _Tidy(); + this->assign(_Right); + } + + _Myt& assign(const ATL::CStringT<_Elem, _ULS_StrTraitMFC< _Elem >>& _Right) + { + _Tidy(); + static_assert(!_Cleaner::value, "atl-string can't assign to a managed unreal_string"); + + this->_Bx._Const_Ptr = _Right.GetString(); + this->_Mysize = _Right.GetLength(); + return *this; + } +#endif + + unreal_string(const std::vector<_Elem>& _Right) + { + _Tidy(); + this->assign(_Right); + } + + unreal_string(const _Myt& _Right) + { + this->assign(_Right); + } + + unreal_string(_Myt&& _Right) + { + _Assign_rv(std::forward<_Myt>(_Right)); + } + + template + unreal_string(const unreal_string<_OtherElem, _OtherCleaner>& _Right) + { + this->assign(_Right); + } + + template + unreal_string(unreal_string<_OtherElem, _OtherCleaner>&& _Right) + { + _Assign_rv(std::forward>(_Right)); + } + + ~unreal_string(void) + { + _Mysize = 0; + _Cleaner::cleanup(this->_Bx._Ptr); + this->_Bx._Const_Ptr = nullptr; + } + + _Myt& assign(const _Elem* _Ptr) + { // shallow copy + if (_Ptr != nullptr) { + this->_Bx._Const_Ptr = _Ptr; + this->_Mysize = native_utils::strlen(_Ptr); + } + return *this; + } + + _Myt& assign(const _Elem* _Ptr, size_t _Length) + { // shallow copy + if (_Ptr != nullptr) { + this->_Bx._Const_Ptr = _Ptr; + this->_Mysize = _Length; + } + return *this; + } + + _Myt& assign(const _Elem* _First, const _Elem* _Last) + { // shallow copy + if (_First != nullptr && _First <= _Last) { + this->_Bx._Const_Ptr = _First; + this->_Mysize = _Last - _First; + } + return *this; + } + + _Myt& assign(_Elem* _Ptr) + { // shallow copy + if (_Ptr != nullptr) { + this->_Bx._Ptr = _Ptr; + this->_Mysize = native_utils::strlen(_Ptr); + } + return *this; + } + + _Myt& assign(_Elem* _Ptr, size_t _Length) + { // shallow copy + if (_Ptr != nullptr) { + this->_Bx._Ptr = _Ptr; + this->_Mysize = _Length; + } + return *this; + } + + _Myt& assign(_Elem* _First, _Elem* _Last) + { // shallow copy + if (_First != nullptr && _First <= _Last) { + this->_Bx._Ptr = _First; + this->_Mysize = _Last - _First; + } + return *this; + } + + _Myt& assign(const std::basic_string<_Elem>& _Right) + { + static_assert(!_Cleaner::value, "atl-string can't assign to a managed unreal_string"); + + this->_Bx._Const_Ptr = _Right.c_str(); + this->_Mysize = _Right.size(); + return *this; + } + + _Myt& assign(const std::vector<_Elem>& _Right) + { + static_assert(!_Cleaner::value, "stl-string can't assign to a managed unreal_string"); + + this->_Bx._Const_Ptr = _Right.data(); + this->_Mysize = _Right.size(); + return *this; + } + + _Myt& assign(const _Myt& _Right) + { + static_assert(!_Cleaner::value, "the managed unreal string can't assign to this managed unreal_string object!"); + + _Tidy(); + ::memcpy(this, &_Right, sizeof(*this)); + return *this; + } + + _Myt& assign(_Myt&& _Right) + { + if (this != &_Right) + _Assign_rv(std::forward<_Myt>(_Right)); + return *this; + } + + template + _Myt& assign(const unreal_string<_OtherElem, _OtherCleaner>& _Right) + { + static_assert(std::is_same<_Elem, _OtherElem>::value, "can't assign unreal string assign, type not same!"); + static_assert(!_Cleaner::value || !_OtherCleaner::value, "the unreal string can't assign to this managed unreal_string object!"); + + _Tidy(); + ::memcpy(this, &_Right, sizeof(*this)); + return *this; + } + + template + _Myt& assign(unreal_string<_OtherElem, _OtherCleaner>&& _Right) + { + if (this != &_Right) + _Assign_rv(std::forward>(_Right)); + return *this; + } + + template + void _Assign_rv(unreal_string<_OtherElem, _OtherCleaner>&& _Right) + { + ::memcpy(this, &_Right, sizeof(*this)); + + if (this->managed()) + _Right._Tidy(); + } + + void reserve(size_t capacity) + { + if (this->_Capacity < capacity) + { + this->_Capacity = capacity; + this->_Bx._Ptr = (_Elem*)realloc(this->_Bx._Ptr/*nullptr ok*/, _Capacity << ULS_ELEM_SHIFT); + } + } + + void cappend(const _Elem* _Ptr, size_t _Count) + { + static_assert(_Cleaner::value, "only managed_cstring is support append operation!"); + + if (_Count > 0) { + if (this->_Bx._Ptr == nullptr) { + _Capacity = (_Count * 3) >> 1; // 1.5 + _Mysize = _Count; + this->_Bx._Ptr = (_Elem*)malloc(_Capacity << ULS_ELEM_SHIFT); + ::memcpy(this->_Bx._Ptr, _Ptr, _Count << ULS_ELEM_SHIFT); + } + else { + auto _Newsize = _Mysize + _Count; + if (_Newsize > _Capacity) + { + _Capacity = (_Newsize * 3) >> 1; + this->_Bx._Ptr = (_Elem*)realloc(this->_Bx._Ptr, _Capacity << ULS_ELEM_SHIFT); + } + + ::memcpy(this->_Bx._Ptr + ( (_Mysize) << ULS_ELEM_SHIFT ), _Ptr, _Count << ULS_ELEM_SHIFT); + + _Mysize = _Newsize; + } + } + } + + _Elem* deatch(void) + { // detach without memory destory for managed string or unmanaged string + auto _Ptr = this->_Bx._Ptr; + memset(this, 0x0, sizeof(*this)); + return _Ptr; + } + + _Myt& operator=(_Elem *_Ptr) + { // assign [_Ptr, ) + return (this->assign(_Ptr)); + } + + _Myt& operator=(const _Elem *_Ptr) + { // assign [_Ptr, ) + return (this->assign(_Ptr)); + } + + _Myt& operator=(const std::basic_string<_Elem>& _Right) + { // assign [_Ptr, ) + return (this->assign(_Right)); + } + + _Myt& operator=(const _Myt& _Right) + { + return this->assign(_Right); + } + + _Myt& operator=(_Myt&& _Right) + { + return this->assign(_Right); + } + + template + _Myt& operator=(const unreal_string<_OtherElem, _OtherCleaner>& _Right) + { + return this->assign(_Right); + } + + template + _Myt& operator=(unreal_string<_OtherElem, _OtherCleaner>&& _Right) + { + return this->assign(_Right); + } + + _Myt& operator+=(const _Myt& _Right); + + _Myt& operator+=(const _Elem *_Ptr); + + _Myt& operator+=(_Elem _Ch); + + static const bool managed(void) + { // return if free memory automatically + return _Cleaner::value; + } + + void set_size(size_t _Newsize) + { + this->_Mysize = _Newsize; + } + + void shrink(size_t _Newsize) + { + if (_Mysize > _Newsize) + { + this->_Mysize = _Newsize; + } + } + + _Elem& at(size_t _Off) + { // subscript nonmutable sequence + return (this->_Bx._Ptr[_Off]); + } + + const _Elem& at(size_t _Off) const + { // subscript nonmutable sequence + return (this->_Bx._Const_Ptr[_Off]); + } + + _Elem& operator[](size_t _Off) + { // subscript nonmutable sequence + return (this->_Bx._Ptr[_Off]); + } + + const _Elem& operator[](size_t _Off) const + { // subscript nonmutable sequence + return (this->_Bx._Const_Ptr[_Off]); + } + + std::basic_string<_Elem> to_string(void) const + { // deep copy: return a c++ stl string + static const _Elem s_empty[] = { (_Elem)0 }; + if (!this->empty()) { + return std::basic_string<_Elem>(this->_Bx._Const_Ptr, this->size()); + } + return s_empty; + } + + const _Elem* c_str(void) const + { // return pointer to null-terminated nonmutable array + if (this->_Bx._Const_Ptr != nullptr && this->_Mysize > 0) { + return this->_Bx._Const_Ptr; + } + static const _Elem s_empty[] = { (_Elem)0 }; + return s_empty; + } + + const _Elem* data(void) const + { // return pointer to nonmutable array + return this->c_str(); + } + + const _Elem*& ldata(void) + { // return internal pointer which can be change by exnternal, use careful + return this->_Bx._Const_Ptr; + } + + size_t& lsize() + { + return _Mysize; + } + + size_t& llength() + { + return _Mysize; + } + + size_t length(void) const + { // return length of sequence + return _Mysize; + } + + size_t size(void) const + { // return length of sequence + return _Mysize; + } + + void clear(void) + { + _Mysize = 0; + } + + bool empty(void) const + { + return 0 == this->_Mysize || nullptr == this->_Bx._Ptr; + } + + int compare(const _Elem* _Ptr) const + { // regard right as null-terminated string + if (this->empty()) + return (_Ptr == nullptr || *_Ptr == 0x0) ? 0 : -1; + else { + + if (_Ptr == nullptr) + return 1; + + int diff = 0; + size_t _N0 = 0; + + for (;;) + { + if (*_Ptr == 0x0) { + diff = _Mysize - _N0; + break; + } + + if (_N0 >= _Mysize) + { // Left terminated, right not terminated. + diff = -1; + break; + } + + diff = (this->_Bx._Ptr[_N0++]) - *_Ptr++; + if (diff != 0) { + break; + } + } + + return diff; + } + } + + int compare(const _Elem* _Right, size_t _Count) const + { + if (this->empty()) + return (_Right == nullptr || _Count == 0 || *_Right == 0x0) ? 0 : -1; + else { + if (_Right != nullptr) + { + int diff = memcmp(this->_Bx._Ptr, _Right, (_Mysize < _Count ? _Mysize : _Count) << (sizeof(_Elem) >> 1)); + return (diff != 0) ? diff : (static_cast(_Mysize)-static_cast(_Count)); + } + else { + return 1; + } + } + } + + int compare(const std::basic_string<_Elem>& _Right) const + { + return this->compare(_Right.c_str(), _Right.length()); + } + + template inline + int compare(const unreal_string<_Elem, _OtherCleaner>& _Right) const + { + return this->compare(_Right.c_str(), _Right.length()); + } + + operator std::basic_string<_Elem>(void) const + { + return this->to_string(); + } + + std::string substr(std::string::size_type _Off, std::string::size_type _Count = std::string::npos) const + { + return this->to_string().substr(_Off, _Count); + } + + void free_any(void) const + { + if (_Bx._Ptr != nullptr) { + free(_Bx._Ptr); + } + } + + void delete_any(void) const + { + if (_Bx._Ptr != nullptr) { + delete[](_Bx._Ptr); + } + } + + protected: + void _Tidy(void) + { + ::memset(this, 0x0, sizeof(*this)); + } + + private: + enum + { // length of internal buffer, [1, 16] + _BUF_SIZE = 16 / sizeof(_Elem) < 1 ? 1 + : 16 / sizeof(_Elem) + }; + enum + { // roundup mask for allocated buffers, [0, 15] + _ALLOC_MASK = sizeof(_Elem) <= 1 ? 15 + : sizeof(_Elem) <= 2 ? 7 + : sizeof(_Elem) <= 4 ? 3 + : sizeof(_Elem) <= 8 ? 1 : 0 + }; + union _Bxty + { // storage for small buffer or pointer to larger one + //_Elem _Buf[_BUF_SIZE]; + const _Elem* _Const_Ptr; // always shallow copy + _Elem* _Ptr; // managed pointer + //char _Alias[_BUF_SIZE]; // to permit aliasing + } _Bx; + size_t _Mysize; + size_t _Capacity; + }; + + /// operator + + template inline + std::basic_string<_Elem> operator+( + const unreal_string<_Elem, _Cleaner>& _Left, + const unreal_string<_Elem, _Cleaner>& _Right) + { // unreal_string + unreal_string + return (_Left.to_string() + _Right.to_string()); + } + + template inline + std::basic_string<_Elem> operator+( + const unreal_string<_Elem, _Cleaner>& _Left, + const std::string& _Right) + { // unreal_string + std::string + return (_Left.to_string() + _Right); + } + + template inline + std::basic_string<_Elem> operator+( + const unreal_string<_Elem, _Cleaner>& _Left, + const _Elem* _Right) + { // unreal_string + NTCS + return (_Left.to_string() + _Right); + } + + template inline + std::basic_string<_Elem> operator+( + const std::string& _Left, + const unreal_string<_Elem, _Cleaner>& _Right) + { // std::string + unreal_string + return (_Left + _Right.c_str()); + } + + template inline + std::basic_string<_Elem> operator+( + const _Elem* _Left, + const unreal_string<_Elem, _Cleaner>& _Right) + { // NTCS + unreal_string + return (std::string(_Left) + _Right.c_str()); + } + + /// operator comparands + template inline + bool operator==( + const unreal_string<_Elem, _Cleaner>& _Left, + const unreal_string<_Elem, _Cleaner>& _Right) + { // test for unreal_string equality + return (_Left.compare(_Right) == 0); + } + + template inline + bool operator==( + const _Elem* _Left, + const unreal_string<_Elem, _Cleaner>& _Right) + { // test for NTCS vs. unreal_string equality + return (_Right.compare(_Left) == 0); + } + + template inline + bool operator==( + const unreal_string<_Elem, _Cleaner>& _Left, + const _Elem* _Right) + { // test for unreal_string vs. NTCS equality + return (_Left.compare(_Right) == 0); + } + + template inline + bool operator==( + const std::basic_string<_Elem>& _Left, + const unreal_string<_Elem, _Cleaner>& _Right) + { // test for std::string vs. unreal_string equality + return (_Right.compare(_Left.c_str(), _Left.length()) == 0); + } + + template inline + bool operator==( + const unreal_string<_Elem, _Cleaner>& _Left, + const std::basic_string<_Elem>& _Right) + { // test for unreal_string vs. std::string equality + return (_Left.compare(_Right.c_str(), _Right.length()) == 0); + } + + template inline + bool operator!=( + const unreal_string<_Elem, _Cleaner>& _Left, + const unreal_string<_Elem, _Cleaner>& _Right) + { // test for unreal_string inequality + return (!(_Left == _Right)); + } + + template inline + bool operator!=( + const _Elem* _Left, + const unreal_string<_Elem, _Cleaner>& _Right) + { // test for NTCS vs. unreal_string inequality + return (!(_Left == _Right)); + } + + template inline + bool operator!=( + const unreal_string<_Elem, _Cleaner>& _Left, + const _Elem* _Right) + { // test for unreal_string vs. NTCS inequality + return (!(_Left == _Right)); + } + + template inline + bool operator!=( + const std::basic_string<_Elem>& _Left, + const unreal_string<_Elem, _Cleaner>& _Right) + { // test for std::string vs. unreal_string inequality + return (!(_Left == _Right)); + } + + template inline + bool operator!=( + const unreal_string<_Elem, _Cleaner>& _Left, + const std::basic_string<_Elem>& _Right) + { // test for unreal_string vs. std::string inequality + return (!(_Left == _Right)); + } + + template inline + bool operator<( + const unreal_string<_Elem, _Cleaner>& _Left, + const unreal_string<_Elem, _Cleaner>& _Right) + { // test if unreal_string < unreal_string + return (_Left.compare(_Right) < 0); + } + + template inline + bool operator<( + const _Elem* _Left, + const unreal_string<_Elem, _Cleaner>& _Right) + { // test if NTCS < unreal_string + return (_Right.compare(_Left) > 0); + } + + template inline + bool operator<( + const unreal_string<_Elem, _Cleaner>& _Left, + const _Elem* _Right) + { // test if unreal_string < NTCS + return (_Left.compare(_Right) < 0); + } + + template inline + bool operator<( + const std::basic_string<_Elem>& _Left, + const unreal_string<_Elem, _Cleaner>& _Right) + { // test if std::string < unreal_string + return (_Left.compare(_Right.c_str()) > 0); + } + + template inline + bool operator<( + const unreal_string<_Elem, _Cleaner>& _Left, + const std::basic_string<_Elem>& _Right) + { // test if unreal_string < std::string + return (_Right.compare(_Left.c_str()) < 0); + } + + template inline + bool operator>( + const unreal_string<_Elem, _Cleaner>& _Left, + const unreal_string<_Elem, _Cleaner>& _Right) + { // test if unreal_string > unreal_string + return (_Right < _Left); + } + + template inline + bool operator>( + const _Elem* _Left, + const unreal_string<_Elem, _Cleaner>& _Right) + { // test if NTCS > unreal_string + return (_Right < _Left); + } + + template inline + bool operator>( + const unreal_string<_Elem, _Cleaner>& _Left, + const _Elem* _Right) + { // test if unreal_string > NTCS + return (_Right < _Left); + } + + template inline + bool operator>( + const std::basic_string<_Elem>& _Left, + const unreal_string<_Elem, _Cleaner>& _Right) + { // test if std::string > unreal_string + return (_Right < _Left); + } + + template inline + bool operator>( + const unreal_string<_Elem, _Cleaner>& _Left, + const std::basic_string<_Elem>& _Right) + { // test if unreal_string > std::string + return (_Right < _Left); + } + + template inline + bool operator<=( + const unreal_string<_Elem, _Cleaner>& _Left, + const unreal_string<_Elem, _Cleaner>& _Right) + { // test if unreal_string <= unreal_string + return (!(_Right < _Left)); + } + + template inline + bool operator<=( + const _Elem* _Left, + const unreal_string<_Elem, _Cleaner>& _Right) + { // test if NTCS <= unreal_string + return (!(_Right < _Left)); + } + + template inline + bool operator<=( + const unreal_string<_Elem, _Cleaner>& _Left, + const _Elem* _Right) + { // test if unreal_string <= NTCS + return (!(_Right < _Left)); + } + + template inline + bool operator<=( + const std::basic_string<_Elem>& _Left, + const unreal_string<_Elem, _Cleaner>& _Right) + { // test if std::string <= unreal_string + return (!(_Right < _Left)); + } + + template inline + bool operator<=( + const unreal_string<_Elem, _Cleaner>& _Left, + const std::basic_string<_Elem>& _Right) + { // test if unreal_string <= std::string + return (!(_Right < _Left)); + } + + template inline + bool operator>=( + const unreal_string<_Elem, _Cleaner>& _Left, + const unreal_string<_Elem, _Cleaner>& _Right) + { // test if unreal_string >= unreal_string + return (!(_Left < _Right)); + } + + template inline + bool operator>=( + const _Elem* _Left, + const unreal_string<_Elem, _Cleaner>& _Right) + { // test if NTCS >= unreal_string + return (!(_Left < _Right)); + } + + template inline + bool operator>=( + const unreal_string<_Elem, _Cleaner>& _Left, + const _Elem* _Right) + { // test if unreal_string >= NTCS + return (!(_Left < _Right)); + } + + template inline + bool operator>=( + const std::basic_string<_Elem>& _Left, + const unreal_string<_Elem, _Cleaner>& _Right) + { // test if std::string >= unreal_string + return (!(_Left < _Right)); + } + + template inline + bool operator>=( + const unreal_string<_Elem, _Cleaner>& _Left, + const std::basic_string<_Elem>& _Right) + { // test if unreal_string >= std::string + return (!(_Left < _Right)); + } + + /// operator << + template inline + std::basic_ostream<_Elem>& operator<<( + std::basic_ostream<_Elem>& _Ostr, + const unreal_string<_Elem, _Cleaner>& _Str) + { // insert a unreal_string + if (!_Str.empty()) { + _Ostr << _Str.c_str(); + } + return (_Ostr); + } + +}; // namespace: purelib + + +/* unreal_string hash, support unordered container. */ +namespace std { + // FUNCTION _Hash_seq + inline size_t _FNV1a_hash(const void* _First, size_t _Count) + { // FNV-1a hash function for bytes in [_First, _First+_Count) +#if defined(_M_X64) || defined(_LP64) || defined(__x86_64) || defined(_WIN64) + static_assert(sizeof(size_t) == 8, "This code is for 64-bit size_t."); + const size_t _FNV_offset_basis = 14695981039346656037ULL; + const size_t _FNV_prime = 1099511628211ULL; + +#else /* defined(_M_X64), etc. */ + static_assert(sizeof(size_t) == 4, "This code is for 32-bit size_t."); + const size_t _FNV_offset_basis = 2166136261U; + const size_t _FNV_prime = 16777619U; +#endif /* defined(_M_X64), etc. */ + + size_t _Val = _FNV_offset_basis; + for (size_t _Next = 0; _Next < _Count; ++_Next) + { // fold in another byte + _Val ^= (size_t)static_cast(_First)[_Next]; + _Val *= _FNV_prime; + } + +#if 0 // Follow code are removed from VS2015 +#if defined(_M_X64) || defined(_LP64) || defined(__x86_64) || defined(_WIN64) + static_assert(sizeof(size_t) == 8, "This code is for 64-bit size_t."); + _Val ^= _Val >> 32; + +#else /* defined(_M_X64), etc. */ + static_assert(sizeof(size_t) == 4, "This code is for 32-bit size_t."); +#endif /* defined(_M_X64), etc. */ +#endif + return (_Val); + } + + // optional hash functions +#if 0 + inline size_t _BKDR_hash(const unsigned char* key, size_t len) + { + static size_t seed = 16777619U; // 31 131 1313 13131 131313 etc.. + size_t hash = 0; + + while (len-- > 0) + { + hash = hash * seed + (*key++); + } + + return (hash & 0x7FFFFFFF); + } + + inline size_t _Times33_hash(const unsigned char* key, size_t len) + { + size_t nHash = 0; + + while (len-- > 0) + nHash = (nHash << 5) + nHash + *key++; + + return nHash; + } +#endif + + template + struct hash < purelib::unreal_string<_Elem, _Cleaner> > + { // hash functor for basic_string + typedef purelib::unreal_string<_Elem, _Cleaner> _Kty; + + size_t operator()(const _Kty& _Keyval) const + { // hash _Keyval to size_t value by pseudorandomizing transform +#if defined(__APPLE__) + return std::__do_string_hash(_Keyval.data(), _Keyval.data() + _Keyval.size()); +#elif defined(__linux__) + return std::_Hash_impl::hash(_Keyval.data(), _Keyval.size() << (sizeof(_Elem) >> 1) ); +#else + return _FNV1a_hash(_Keyval.c_str(), _Keyval.size() << ULS_ELEM_SHIFT); +#endif + } + }; +} + +#endif +/* _UNREAL_STRING_H_ */ + +/* +* Copyright (c) 2012-2016 by halx99 ALL RIGHTS RESERVED. +* Consult your license regarding permissions and restrictions. +V3.0:2011 */ + diff --git a/src/xxbswap.h b/src/xxbswap.h new file mode 100644 index 0000000000000000000000000000000000000000..b3d7ee5e2c4b382a5dfffc23bf4dbbf75b5d8787 --- /dev/null +++ b/src/xxbswap.h @@ -0,0 +1,188 @@ +#ifndef _XXBSWAP_H_ +#define _XXBSWAP_H_ + +#if defined(_WIN32) && !defined(WP8) && !defined(WINRT) +/* +* +__declspec(naked) uint16_t __cdecl __bswap16(uint16_t) +{ + __asm + { + // 保存寄存器(若没有寄存器需要存,以下3条指令代码可省略) + push ebp; + mov ebp, esp; + push esi + + mov eax, dword ptr[ebp + 8]; // 这里如果没有寄存保存,可直接使用esp, 注: 16汇编不支持esp作为基地址寄存器 + ror ax, 8; + + // 恢复寄存器(若没有寄存器需要存,以下3条指令代码可省略) + pop esi; + mov esp ebp + pop ebp; + + ret ; + } +} +* +*/ +inline +__declspec(naked) uint16_t __cdecl __bswap16(uint16_t) +{ + __asm + { + mov eax, dword ptr[esp + 4]; + mov ecx, eax; + shl eax, 8; eax = 0x00112200; + sar ecx, 8; ecx = 0x00000011; + or eax, ecx; + ret ; + } +} + +inline +__declspec(naked) uint32_t __cdecl __bswap32(uint32_t) +{ + __asm + { + mov eax, dword ptr[esp + 4]; + mov ecx, eax; + + ror ecx, 8; ecx = 0x44112233 + and ecx, 0xFF00FF00; ecx = 0x44002200 + + rol eax, 8; eax = 0x22334411 + and eax, 0x00FF00FF; eax = 0x00330011 + + or eax, ecx; eax = 0x44332211 + + ret ; + } +} + +/* 当release模式是,编译器优化代码可能会使用除了作为返回值寄存器 + (edx:eax) 之外的其他寄存器,因此在写naked内联汇编函数时,必须 + 保存相关寄存器,否则会产生意想不到的后果。 + 而由windows htons和htonl可知,ecx也不需要保存, 以下汇编代码 + 只适用于windows 平台 +*/ +inline +__declspec(naked) uint64_t __cdecl __bswap64(uint64_t) +{ + __asm + { + mov edx, dword ptr[esp + 4]; + mov eax, dword ptr[esp + 8]; + + ; --- swap low 4 bytes + mov ecx, eax; ecx = eax = 0x11223344 + ror ecx, 8; ecx = 0x44112233 + and ecx, 0xFF00FF00; ecx = 0x44002200 + + rol eax, 8; eax = 0x22334411 + and eax, 0x00FF00FF; eax = 0x00330011 + + or eax, ecx; eax = 0x44332211 + + ; --- swap high 4 bytes + mov ecx, edx; ecx = edx = 0x55667788 + ror ecx, 8; ecx = 0x88556677 + and ecx, 0xFF00FF00; ecx = 0x88006600 + + rol edx, 8; edx = 0x66778855 + and edx, 0x00FF00FF; edx = 0x00770055 + + or edx, ecx; edx = 0x88776655 + + ret ; + } +} + +#else + +#define __BSWAP16(from,to) \ +{ \ + __asm__ __volatile__( \ + "mov %1, %%ax\n\t" \ + "ror $8, %%ax\n\t" \ + "mov %%ax, %0\n\t" \ + : "=r"(to) \ + : "r"(from) \ + : "cc", "memory", "ax" \ + ); \ +} + + +#define __BSWAP32(from,to) \ +{ \ + __asm__ __volatile__( \ + "movl %1, %%eax\n\t" \ + "movl %%eax, %%ecx\n\t" \ + "rorl $8, %%ecx\n\t" \ + "andl $0xff00ff00, %%ecx\n\t" \ + "roll $8, %%eax\n\t" \ + "andl $0x00ff00ff, %%eax\n\t" \ + "orl %%ecx, %%eax\n\t" \ + "movl %%eax, %0\n\t" \ + : "=r"(to) \ + : "r"((uint32_t)from) \ + : "cc", "memory" \ + ); \ +} + +#define __BSWAP64(from,to) \ +{ \ + uint32_t& l_ref = *( (uint32_t*)&to ); \ + uint32_t& h_ref = *( (uint32_t*)&to + 1 ); \ + __asm__ __volatile__( \ + "movl %3, %%eax\n\t" \ + "movl %%eax, %%ecx\n\t" \ + "rorl $8, %%ecx\n\t" \ + "andl $0xff00ff00, %%ecx\n\t" \ + "roll $8, %%eax\n\t" \ + "andl $0x00ff00ff, %%eax\n\t" \ + "orl %%ecx, %%eax\n\t" \ + "movl %%eax, %0\n\t" \ + "movl %2, %%eax\n\t" \ + "movl %%eax, %%ecx\n\t" \ + "rorl $8, %%ecx\n\t" \ + "andl $0xff00ff00, %%ecx\n\t" \ + "roll $8, %%eax\n\t" \ + "andl $0x00ff00ff, %%eax\n\t" \ + "orl %%ecx, %%eax\n\t" \ + "movl %%eax, %1\n\t" \ + : "=r"(l_ref), "=r"(h_ref) \ + : "r"(*( (uint32_t*)&from )), "r"(*( (uint32_t*)&from + 1 )) \ + : "cc", "memory", "eax", "ecx" \ + ); \ +} + +inline uint16_t __bswap16(uint16_t fromval) +{ + uint16_t toval = 0; + //__BSWAP16(fromval, toval); + return toval; +} + +inline uint32_t __bswap32(uint32_t fromval) +{ + uint32_t toval = 0; + //__BSWAP32(fromval, toval); + return toval; +} + +inline uint64_t __bswap64(uint64_t fromval) +{ + uint64_t toval = 0; + //__BSWAP64(fromval, toval); + return toval; +} + +#endif + +#endif // __BSWAP +/* +* Copyright (c) 2012-2013 by X.D. Guo ALL RIGHTS RESERVED. +* Consult your license regarding permissions and restrictions. +**/ + diff --git a/src/xxfree.h b/src/xxfree.h new file mode 100644 index 0000000000000000000000000000000000000000..b711e701ec7e0a87f0e5af2e1fbfdc6bdd9211f2 --- /dev/null +++ b/src/xxfree.h @@ -0,0 +1,106 @@ +#ifndef _XXFREE_H_ +#define _XXFREE_H_ +#include + +namespace purelib { + +namespace gc { + +// TEMPLATE STRUCT destroyer +template +struct _Free +{ + typedef void (*type)(_Ty*); +}; + +// c++ single object deleter +template +void object_free(_Ty* _Ptr) +{ + delete _Ptr; +} + +// c++ objects array free function template +template +void array_free(_Ty* _Ptr) +{ + delete [] _Ptr; +} + +// pod type object free function template +template +void pod_free(_Ty* _Ptr) +{ + free(_Ptr); +} + +// pseudo free, do not influence the object +template +void pseudo_free(_Ty*) +{ +} + +/// template free v2 + // TEMPLATE CLASS integral_constant +template + struct integral_constant + { // convenient template for integral constant types + static const _Ty value = _Val; + + typedef _Ty value_type; + typedef integral_constant<_Ty, _Val> type; + }; + +typedef integral_constant true_type; +typedef integral_constant false_type; + +// object cleaner, do not influence the object +template +struct object_cleaner : true_type +{ + static void cleanup(_Ty* _Ptr) + { + delete _Ptr; + } +}; + +// array cleaner, do not influence the object +template +struct array_cleaner : true_type +{ + static void cleanup(_Ty* _Ptr) + { + delete [] _Ptr; + } +}; + +// pod cleaner, do not influence the object +template +struct pod_cleaner : true_type +{ + static void cleanup(_Ty* _Ptr) + { + free(_Ptr); + } +}; + +// pseudo cleaner, do not influence the object +template +struct pseudo_cleaner : false_type +{ + static void cleanup(_Ty*) + { + } +}; + +}; // namespace: purelib::gc +}; // namespace: purelib + +#endif + /* _XXFREE_H_ */ +/* +* Copyright (c) 2012-2013 by X.D. Guo ALL RIGHTS RESERVED. +* Consult your license regarding permissions and restrictions. +V3.0:2011 */ + diff --git a/src/xxlcall.h b/src/xxlcall.h index 63cdc31a5f55bcc03231087800bae43c9dcf9a1a..15bbea4ab698e5d67c5559343c5e8e4284d7364d 100644 --- a/src/xxlcall.h +++ b/src/xxlcall.h @@ -317,18 +317,17 @@ void luax_vpusharg(lua_State* L, int& carg, int& narg, void* arg) } /// cocos2d-x object support -#define LUAX_VCALL_ADD_ANY_SUPPORT(type,prefix) \ +#define LUAX_VCALL_ADD_ANY_SUPPORT(type,prefix,ltype) \ inline \ void luax_vpusharg(lua_State* L, int& carg, int& narg, type* arg) \ { \ ++carg; \ if (lua_checkstack(L, 1)) \ - object_to_luaval(L,prefix #type, arg),/*tolua_pushuserdata(L, arg),*/ ++narg; \ + object_to_luaval(L,prefix ltype, arg),/*tolua_pushuserdata(L, arg),*/ ++narg; \ } -#define LUAX_VCALL_ADD_CUSTOM_SUPPORT(type) LUAX_VCALL_ADD_ANY_SUPPORT(type, "zysj.") -#define LUAX_VCALL_ADD_CCOBJ_SUPPORT(type) LUAX_VCALL_ADD_ANY_SUPPORT(type, "cc.") -#define LUAX_VCALL_ADD_CCUI_SUPPORT(type) LUAX_VCALL_ADD_ANY_SUPPORT(type, "ccui.") +#define LUAX_VCALL_ADD_CCOBJ_SUPPORT(type) LUAX_VCALL_ADD_ANY_SUPPORT(type,"cc.", #type) +#define LUAX_VCALL_ADD_CCUI_SUPPORT(type,ltype) LUAX_VCALL_ADD_ANY_SUPPORT(type,"ccui.",ltype) template inline void luax_vpusharg(lua_State* L, int& carg, int& narg, _Ty arg1, const _Args&...args) @@ -585,7 +584,7 @@ void luax_vcall(const ref_ptr& refid, const _Args&...args) template inline _Result luax_vxcall(const ref_ptr& refid, const _Args&...args) { - return luax_dovxcall(luax_rawgeti(refid->Id()), luax_refid2a(refid->Id()), args...); + return luax_dovxcall<_Result>(luax_rawgeti(refid->Id()), luax_refid2a(refid->Id()), args...); } // Lua object func call helpers @@ -604,7 +603,7 @@ void luax_vcall(const ref_ptr& lobj, const char* objfunc, const _Args&.. template inline _Result luax_vxcall(const ref_ptr& lobj, const char* objfunc, const _Args&...args) { - return luax_dovxcall(luax_getobjfield(lobj->Id(), objfunc), objfunc, args...); + return luax_dovxcall<_Result>(luax_getobjfield(lobj->Id(), objfunc), objfunc, args...); } /* End of Lua object func call helpers */ diff --git a/src/xxsocket.cpp b/src/xxsocket.cpp index f57028e8c6fce5cd250acb991d908a1c2ad94be2..4c6274fbfd5eb0deac43318ef1c8afa49cff20b3 100644 --- a/src/xxsocket.cpp +++ b/src/xxsocket.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////////////////// // A cross platform socket APIs, support ios & android & wp8 & window store universal app -// version: 2.0 +// version: 2.2 ////////////////////////////////////////////////////////////////////////////////////////// /* The MIT License (MIT) @@ -26,31 +26,31 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "xxsocket.h" -#include #ifdef _DEBUG #include #endif -#if !defined(_WIN32) -#if !defined(ANDROID) +#if !defined(_WIN32) && !defined(ANDROID) #include #endif +#if !defined(_WIN32) || defined(_WINSTORE) + #ifndef IN_CLASSB_NET #define IN_CLASSB_NET 0xffff0000 #endif #ifndef IN_LOOPBACK -#define IN_LOOPBACK(i) (((u_int32_t)(i) & 0xff000000) == 0x7f000000) +#define IN_LOOPBACK(i) (((uint32_t)(i) & 0xff000000) == 0x7f000000) #endif #ifndef IN_LINKLOCALNETNUM -#define IN_LINKLOCALNETNUM (u_int32_t)0xA9FE0000 /* 169.254.0.0 */ +#define IN_LINKLOCALNETNUM (uint32_t)0xA9FE0000 /* 169.254.0.0 */ #endif #ifndef IN_LINKLOCAL -#define IN_LINKLOCAL(i) (((u_int32_t)(i) & IN_CLASSB_NET) == IN_LINKLOCALNETNUM) +#define IN_LINKLOCAL(i) (((uint32_t)(i) & IN_CLASSB_NET) == IN_LINKLOCALNETNUM) #endif #ifndef IN4_IS_ADDR_LOOPBACK @@ -67,7 +67,7 @@ SOFTWARE. #pragma warning(disable: 4996) using namespace purelib; -using namespace purelib::net; +using namespace purelib::inet; #ifdef _WIN32 #undef gai_strerror @@ -88,8 +88,10 @@ namespace compat { #ifdef SPRINTF_CHAR # define SPRINTF(x) strlen(sprintf/**/x) #else +#ifndef SPRINTF # define SPRINTF(x) (/*(size_t)*/sprintf x) #endif +#endif /* * Define constants based on RFC 883, RFC 1034, RFC 1035 @@ -447,11 +449,7 @@ static int return (0); memcpy(dst, tmp, NS_IN6ADDRSZ); return (1); -} -}; -}; -}; -}; +}}}}}; int xxsocket::getipsv(void) { @@ -549,74 +547,84 @@ int xxsocket::getipsv(void) int xxsocket::xpconnect(const char* hostname, u_short port) { - auto ep = xxsocket::resolve(hostname, port); auto flags = getipsv(); - switch (ep.af()) - { - case AF_INET: - if (flags & ipsv_ipv4) { - return pconnect(ep); - } - else if (flags & ipsv_ipv6) { - return pconnect(xxsocket::resolve_v6(hostname, port)); - } - break; - case AF_INET6: - if (flags & ipsv_ipv6) { - return pconnect(ep); + int error = -1; + + xxsocket::resolve_i([&](const ip::endpoint& ep) { + switch (ep.af()) + { + case AF_INET: + if (flags & ipsv_ipv4) { + error = pconnect(ep); + } + else if (flags & ipsv_ipv6) { + xxsocket::resolve_i([&](const ip::endpoint& ep6) { + return 0 == (error = pconnect(ep6)); + }, hostname, port, AF_INET6, AI_V4MAPPED); + } + break; + case AF_INET6: + if (flags & ipsv_ipv6) { + error = pconnect(ep); + } + break; } - break; - } - // not support. - return -1; + return error == 0; + }, hostname, port); + + return error; } int xxsocket::xpconnect_n(const char* hostname, u_short port, long timeout_sec) { - auto ep = xxsocket::resolve(hostname, port); auto flags = getipsv(); - switch (ep.af()) - { - case AF_INET: - if (flags & ipsv_ipv4) { - return pconnect_n(ep, timeout_sec); - } - else if (flags & ipsv_ipv6) { - return pconnect_n(xxsocket::resolve_v6(hostname, port), timeout_sec); - } - break; - case AF_INET6: - if (flags & ipsv_ipv6) { - return pconnect_n(ep, timeout_sec); + int error = -1; + + xxsocket::resolve_i([&](const ip::endpoint& ep) { + switch (ep.af()) + { + case AF_INET: + if (flags & ipsv_ipv4) { + error = pconnect_n(ep, timeout_sec); + } + else if (flags & ipsv_ipv6) { + xxsocket::resolve_i([&](const ip::endpoint& ep6) { + return 0 == (error = pconnect_n(ep6, timeout_sec)); + }, hostname, port, AF_INET6, AI_V4MAPPED); + } + break; + case AF_INET6: + if (flags & ipsv_ipv6) { + error = pconnect_n(ep, timeout_sec); + } + break; } - break; - } - // not support. - return -1; + return error == 0; + }, hostname, port); + + return error; } int xxsocket::pconnect(const char* hostname, u_short port) { - auto ep = xxsocket::resolve(hostname, port); - if (this->reopen(ep.af())) - { - return this->connect(ep); - } - return -1; + int error = -1; + xxsocket::resolve_i([&](const ip::endpoint& ep) { + return 0 == (error = pconnect(ep)); + }, hostname, port); + return error; } int xxsocket::pconnect_n(const char* hostname, u_short port, long timeout_sec) { - auto ep = xxsocket::resolve(hostname, port); - if (this->reopen(ep.af())) - { - return this->connect_n(ep, timeout_sec); - } - return -1; + int error = -1; + xxsocket::resolve_i([&](const ip::endpoint& ep) { + return 0 == (error = pconnect_n(ep, timeout_sec)); + }, hostname, port); + return error; } int xxsocket::pconnect(const ip::endpoint& ep) @@ -700,7 +708,7 @@ ip::endpoint xxsocket::resolve_v6(const char* hostname, unsigned short port) memcpy(&ep, answer->ai_addr, answer->ai_addrlen); switch (answer->ai_family) { - case AF_INET6: + case AF_INET6: // Must be AF_INET6 ep.in6_.sin6_port = htons(port); break; default:; @@ -711,7 +719,23 @@ ip::endpoint xxsocket::resolve_v6(const char* hostname, unsigned short port) return ep; } -xxsocket::xxsocket(void) : fd(bad_sock) +bool xxsocket::resolve(std::vector& endpoints, const char* hostname, unsigned short port) +{ + return resolve_i([&](const ip::endpoint& ep) { + endpoints.push_back(ep); + return false; + }, hostname, port); +} + +bool xxsocket::resolve_v6(std::vector& endpoints, const char* hostname, unsigned short port) +{ + return resolve_i([&](const ip::endpoint& ep) { + endpoints.push_back(ep); + return false; + }, hostname, port, AF_INET6, AI_V4MAPPED); +} + +xxsocket::xxsocket(void) : fd(invalid_socket) { } @@ -719,7 +743,7 @@ xxsocket::xxsocket(socket_native_type h) : fd(h) { } -xxsocket::xxsocket(xxsocket&& right) : fd(bad_sock) +xxsocket::xxsocket(xxsocket&& right) : fd(invalid_socket) { swap(right); } @@ -737,7 +761,7 @@ xxsocket& xxsocket::operator=(xxsocket&& right) return swap(right); } -xxsocket::xxsocket(int af, int type, int protocol) : fd(bad_sock) +xxsocket::xxsocket(int af, int type, int protocol) : fd(invalid_socket) { open(af, type, protocol); } @@ -752,14 +776,14 @@ xxsocket& xxsocket::swap(xxsocket& who) // avoid fd missing if (!is_open()) { this->fd = who.fd; - who.fd = bad_sock; + who.fd = invalid_socket; } return *this; } bool xxsocket::open(int af, int type, int protocol) { - if (bad_sock == this->fd) + if (invalid_socket == this->fd) { this->fd = ::socket(af, type, protocol); } @@ -776,7 +800,7 @@ bool xxsocket::reopen(int af, int type, int protocol) bool xxsocket::open_ex(int af, int type, int protocol) { #if !defined(WP8) - if (bad_sock == this->fd) + if (invalid_socket == this->fd) { this->fd = ::WSASocket(af, type, protocol, nullptr, 0, WSA_FLAG_OVERLAPPED); @@ -863,13 +887,13 @@ void xxsocket::translate_sockaddrs( bool xxsocket::is_open(void) const { - return this->fd != bad_sock; + return this->fd != invalid_socket; } socket_native_type xxsocket::release(void) { socket_native_type result = this->fd; - this->fd = bad_sock; + this->fd = invalid_socket; return result; } @@ -955,13 +979,13 @@ int xxsocket::connect(socket_native_type s, const ip::endpoint& ep) int xxsocket::connect_n(const char* addr, u_short port, long timeout_sec) { - auto timeout = make_tv(timeout_sec); + timeval timeout{ timeout_sec, 0 }; return connect_n(addr, port, &timeout); } int xxsocket::connect_n(const ip::endpoint& ep, long timeout_sec) { - auto timeout = make_tv(timeout_sec); + timeval timeout{ timeout_sec, 0 }; return connect_n(ep, &timeout); } @@ -973,7 +997,7 @@ int xxsocket::connect_n(const char* addr, u_short port, timeval* timeout) int xxsocket::connect_n(const ip::endpoint& ep, timeval* timeout) { if (xxsocket::connect_n(this->fd, ep, timeout) != 0) { - this->fd = bad_sock; + this->fd = invalid_socket; return -1; } return 0; @@ -1027,12 +1051,12 @@ done: xxsocket::set_last_errno(error); return (-1); } - + /* restore file status flags */ #ifdef _MSC_VER set_nonblocking(s, false); #else - ::fcntl(s, F_SETFL, flags); + ::fcntl(s, F_SETFL, flags); #endif return (0); } @@ -1055,7 +1079,7 @@ int xxsocket::send(const void* buf, int len, int flags) const int xxsocket::send_n(const void* buf, int len, long timeout_sec, int flags) { - auto timeout = make_tv(timeout_sec); + timeval timeout{ timeout_sec, 0 }; return send_n(this->fd, buf, len, &timeout, flags); } @@ -1136,7 +1160,7 @@ int xxsocket::recv(void* buf, int len, int flags) const int xxsocket::recv_n(void* buf, int len, long timeout_sec, int flags) const { - auto timeout = make_tv(timeout_sec); + timeval timeout{ timeout_sec, 0 }; return recv_n(this->fd, buf, len, &timeout, flags); } @@ -1395,7 +1419,7 @@ int xxsocket::set_keepalive(int flag, int idle, int interval, int probes) int xxsocket::set_keepalive(socket_native_type s, int flag, int idle, int interval, int probes) { -#if defined(_WIN32) && !defined(WP8) && !defined(WINRT) +#if defined(_WIN32) && !defined(WP8) && !defined(_WINSTORE) tcp_keepalive buffer_in; buffer_in.onoff = flag; buffer_in.keepalivetime = idle; @@ -1413,18 +1437,13 @@ int xxsocket::set_keepalive(socket_native_type s, int flag, int idle, int interv #else int errcnt = 0; errcnt += set_optval(s, SOL_SOCKET, SO_KEEPALIVE, flag); - //errcnt += set_optval(s, SOL_TCP, TCP_KEEPIDLE, idle); - //errcnt += set_optval(s, SOL_TCP, TCP_KEEPINTVL, interval); - //errcnt += set_optval(s, SOL_TCP, TCP_KEEPCNT, probes); + // errcnt += set_optval(s, SOL_TCP, TCP_KEEPIDLE, idle); + // errcnt += set_optval(s, SOL_TCP, TCP_KEEPINTVL, interval); + // errcnt += set_optval(s, SOL_TCP, TCP_KEEPCNT, probes); return errcnt; #endif } -//int xxsocket::ioctl(long cmd, u_long* argp) const -//{ -// return ::ioctlsocket(this->fd, cmd, argp); -//} - xxsocket::operator socket_native_type(void) const { return this->fd; @@ -1445,17 +1464,17 @@ void xxsocket::close(void) if (is_open()) { ::closesocket(this->fd); - this->fd = bad_sock; + this->fd = invalid_socket; } } -#if defined(_WINSTORE) || defined(WINRT) +#if defined(_WINSTORE) #undef _naked_mark #define _naked_mark #endif void _naked_mark xxsocket::init_ws32_lib(void) { -#if defined(_WIN32) && !defined(_WIN64) && !defined(WINRT) +#if defined(_WIN32) && !defined(_WIN64) && !defined(_WINSTORE) _asm ret; #else return; diff --git a/src/xxsocket.h b/src/xxsocket.h index b4cbf29728e986b5ff0a82e05e4d17460a8e1831..87cf1c7af9fad79f9b664cc685175181f2a5e309 100644 --- a/src/xxsocket.h +++ b/src/xxsocket.h @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////////////////// // A cross platform socket APIs, support ios & android & wp8 & window store universal app -// version: 2.0 +// version: 2.2 ////////////////////////////////////////////////////////////////////////////////////////// /* The MIT License (MIT) @@ -38,6 +38,7 @@ SOFTWARE. #include #include #include +#include #include "politedef.h" #pragma warning(push) @@ -59,7 +60,6 @@ typedef int socklen_t; #else #include #include -#include #include #include #include @@ -79,6 +79,7 @@ typedef int socklen_t; typedef int socket_native_type; #undef socket #endif +#include // common platform header // redefine socket error code for posix api #ifdef _WIN32 @@ -119,7 +120,8 @@ typedef int socket_native_type; #undef EUSERS #undef EDQUOT #undef ESTALE -#undef EREMOTE +#undef EREMOTE +#undef EBADF #define EWOULDBLOCK WSAEWOULDBLOCK #define EINPROGRESS WSAEINPROGRESS @@ -158,6 +160,7 @@ typedef int socket_native_type; #define EDQUOT WSAEDQUOT #define ESTALE WSAESTALE #define EREMOTE WSAEREMOTE +#define EBADF WSAEBADF #endif @@ -183,11 +186,9 @@ namespace purelib { namespace inet { -#define _make_value(b1,b2,b3,b4) ( ( ((uint32_t)(b4) << 24) & 0xff000000 ) | ( ((uint32_t)(b3) << 16) & 0x00ff0000 ) | ( ((uint32_t)(b2) << 8) & 0x0000ff00 ) | ( (uint32_t)(b1) & 0x000000ff ) ) +// #define _make_dotted_decimal(b1,b2,b3,b4) ( ( ((uint32_t)(b4) << 24) & 0xff000000 ) | ( ((uint32_t)(b3) << 16) & 0x00ff0000 ) | ( ((uint32_t)(b2) << 8) & 0x0000ff00 ) | ( (uint32_t)(b1) & 0x000000ff ) ) - - -static const socket_native_type bad_sock = (socket_native_type)-1; +static const socket_native_type invalid_socket = (socket_native_type)-1; static const u_long blocking = 0; static const u_long nonblocking = 1; @@ -340,7 +341,38 @@ public: { ::memset(this, 0x0, sizeof(*this)); } - explicit endpoint(const char* addr, unsigned short port) + explicit endpoint(const addrinfo* info) + { + assign(info); + } + explicit endpoint(const sockaddr* info) + { + assign(info); + } + endpoint(const char* addr, unsigned short port) + { + assign(addr, port); + } + + void assign(const addrinfo* info) + { + ::memcpy(this, info->ai_addr, info->ai_addrlen); + } + + void assign(const sockaddr* addr) + { + switch (addr->sa_family) + { + case AF_INET: + ::memcpy(&in4_, addr, sizeof(sockaddr_in)); + break; + case AF_INET6: + ::memcpy(&in6_, addr, sizeof(sockaddr_in6)); + break; + } + } + + void assign(const char* addr, unsigned short port) { ::memset(this, 0x0, sizeof(*this)); @@ -357,20 +389,22 @@ public: this->in6_.sin6_family = AF_INET6; compat::inet_pton(AF_INET6, addr, &this->in6_.sin6_addr); this->in6_.sin6_port = htons(port); - } + } } - void assign(const sockaddr* addr) + void address(const char* addr) { - // intri_.sa_family = af; - switch(addr->sa_family) - { - case AF_INET: - ::memcpy(&in4_, addr, sizeof(sockaddr_in)); - break; - case AF_INET6: - ::memcpy(&in6_, addr, sizeof(sockaddr_in6)); - break; + /* + * Windows XP no inet_pton or inet_ntop + */ + if (strchr(addr, ':') == nullptr) + { // ipv4 + this->in4_.sin_family = AF_INET; + compat::inet_pton(AF_INET, addr, &this->in4_.sin_addr); + } + else { // ipv6 + this->in6_.sin6_family = AF_INET6; + compat::inet_pton(AF_INET6, addr, &this->in6_.sin6_addr); } } @@ -425,15 +459,6 @@ public: }; -inline -timeval make_tv(uint32_t sec, uint32_t usec = 0) -{ - timeval tv; - tv.tv_sec = sec; - tv.tv_usec = usec; - return tv; -} - // supported internet protocol flags enum { ipsv_unavailable = 0, @@ -854,15 +879,59 @@ public: static const char* get_error_msg(int error); /// - /// Resolve as ipv4 or ipv6 endpoint + /// Resolve as ipv4 or ipv6 endpoint, only return first available endpoint /// static ip::endpoint resolve(const char* hostname, unsigned short port = 0); /// - /// Force resolve as ipv6 endpoint + /// Force resolve as ipv6 endpoint, only return first available endpoint /// static ip::endpoint resolve_v6(const char* hostname, unsigned short port = 0); + /// + /// Resolve as ipv4 or ipv6 endpoints + /// + static bool resolve(std::vector& endpoints, const char* hostname, unsigned short port = 0); + + /// + /// Force resolve as ipv6 endpoints + /// + static bool resolve_v6(std::vector& endpoints, const char* hostname, unsigned short port = 0); + + /// + /// Resolve as ipv4 or ipv6 endpoints with callback + /// + template inline + static bool resolve_i(const _Fty& callback, const char* hostname, unsigned short port = 0, int af = 0, int flags = 0) + { + addrinfo hint; + memset(&hint, 0x0, sizeof(hint)); + hint.ai_family = af; + hint.ai_flags = flags; + + addrinfo* answerlist = nullptr; + char buffer[sizeof "65535"] = { '\0' }; + const char* service = nullptr; + if (port > 0) { + sprintf(buffer, "%u", port); // It's enough for unsigned short, so use sprintf ok. + service = buffer; + } + getaddrinfo(hostname, service, &hint, &answerlist); + if (nullptr == answerlist) + return false; + + for (auto answer = answerlist; answer != nullptr; answer = answer->ai_next) { + if (answer->ai_family == AF_INET6 || answer->ai_family == AF_INET) { + if (callback(ip::endpoint(answer))) + break; + } + } + + freeaddrinfo(answerlist); + + return true; + } + private: socket_native_type fd; }; diff --git a/test/Debug/xxsocket_test-vc14.exe b/test/Debug/xxsocket_test-vc14.exe deleted file mode 100644 index c39f247a49628521901b0193683e09cf5f137c6f..0000000000000000000000000000000000000000 Binary files a/test/Debug/xxsocket_test-vc14.exe and /dev/null differ diff --git a/test/x64/Debug/xxsocket_test-vc14.exe b/test/x64/Debug/xxsocket_test-vc14.exe deleted file mode 100644 index afcceb92295341e6021f2019146ef0de344df403..0000000000000000000000000000000000000000 Binary files a/test/x64/Debug/xxsocket_test-vc14.exe and /dev/null differ diff --git a/test/xxsocket_test-vc14.sln b/test/xxsocket_test-vc14.sln index 3e3496ea1eabea9cebb9add07590b527dd193da5..3e1056da55b6f3f11f9fbdab6c8ac2a8e04e2e9c 100644 --- a/test/xxsocket_test-vc14.sln +++ b/test/xxsocket_test-vc14.sln @@ -1,9 +1,11 @@ 锘 Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 -VisualStudioVersion = 14.0.25029.0 +VisualStudioVersion = 14.0.25420.1 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xxsocket_test", "xxsocket_test\xxsocket_test-vc14.vcxproj", "{5D0F6B61-954B-45ED-B3AD-21B5BF077666}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xxsocket_test-vc14", "xxsocket_test\xxsocket_test-vc14.vcxproj", "{5D0F6B61-954B-45ED-B3AD-21B5BF077666}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tcpserver", "tcpserver\tcpserver.vcxproj", "{9524B0C0-490E-42DF-9E66-9091D7B630EE}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -21,6 +23,14 @@ Global {5D0F6B61-954B-45ED-B3AD-21B5BF077666}.Release|x64.Build.0 = Release|x64 {5D0F6B61-954B-45ED-B3AD-21B5BF077666}.Release|x86.ActiveCfg = Release|Win32 {5D0F6B61-954B-45ED-B3AD-21B5BF077666}.Release|x86.Build.0 = Release|Win32 + {9524B0C0-490E-42DF-9E66-9091D7B630EE}.Debug|x64.ActiveCfg = Debug|x64 + {9524B0C0-490E-42DF-9E66-9091D7B630EE}.Debug|x64.Build.0 = Debug|x64 + {9524B0C0-490E-42DF-9E66-9091D7B630EE}.Debug|x86.ActiveCfg = Debug|Win32 + {9524B0C0-490E-42DF-9E66-9091D7B630EE}.Debug|x86.Build.0 = Debug|Win32 + {9524B0C0-490E-42DF-9E66-9091D7B630EE}.Release|x64.ActiveCfg = Release|x64 + {9524B0C0-490E-42DF-9E66-9091D7B630EE}.Release|x64.Build.0 = Release|x64 + {9524B0C0-490E-42DF-9E66-9091D7B630EE}.Release|x86.ActiveCfg = Release|Win32 + {9524B0C0-490E-42DF-9E66-9091D7B630EE}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/test/xxsocket_test/boost_async_client_test.cpp b/test/xxsocket_test/boost_async_client_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fd7a66d74e37b2e0c3eea90edbd46683005f147a --- /dev/null +++ b/test/xxsocket_test/boost_async_client_test.cpp @@ -0,0 +1,256 @@ +// +// async_client.cpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include +#include +#include +#include +#include +#include +#include +#include "select_interrupter.hpp" +#include "async_tcp_client.h" + +using boost::asio::ip::tcp; + +class client +{ +public: + client(boost::asio::io_service& io_service, + const std::string& server, const std::string& path) + : resolver_(io_service), + socket_(io_service), + timeout_check_timer_(io_service) + { + // Form the request. We specify the "Connection: close" header so that the + // server will close the socket after transmitting the response. This will + // allow us to treat all data up until the EOF as the content. + std::ostream request_stream(&request_); + request_stream << "GET " << path << " HTTP/1.0\r\n"; + request_stream << "Host: " << server << "\r\n"; + request_stream << "Accept: */*\r\n"; + request_stream << "Connection: close\r\n\r\n"; + + // Start an asynchronous resolve to translate the server and service names + // into a list of endpoints. + /*tcp::resolver::query query(server, "http"); + resolver_.async_resolve(query, + boost::bind(&client::handle_resolve, this, + boost::asio::placeholders::error, + boost::asio::placeholders::iterator));*/ + handle_resolve(); + } + +private: + void handle_resolve(/*const boost::system::error_code& err, + tcp::resolver::iterator endpoint_iterator*/) + { + if (1) + { + + tcp::resolver::query query("127.0.0.1", "http"); + tcp::resolver::iterator iterator = resolver_.resolve(query); + // v.address(boost::asio::ip::address_v4()) + // Attempt a connection to each endpoint in the list until we + // successfully establish a connection. + boost::asio::async_connect(socket_, iterator, + boost::bind(&client::handle_connect, this, + boost::asio::placeholders::error)); + } + else + { + // std::cout << "Error: " << err.message() << "\n"; + } + } + + void handle_connect(const boost::system::error_code& err) + { + if (!err) + { + // The connection was successful. Send the request. + boost::asio::async_write(socket_, request_, + boost::bind(&client::handle_write_request, this, + boost::asio::placeholders::error)); + } + else + { + std::cout << "Error: " << err.message() << "\n"; + } + } + + void handle_write_request_other_thread(const boost::system::error_code& err) + { + if (!err) + { + printf("其它线程发送完成.\n"); + } + else + { + std::cout << "其它线程发送错误: " << err.message() << "\n"; + } + } + + boost::asio::deadline_timer timeout_check_timer_; + + void handle_write_request(const boost::system::error_code& err) + { + if (!err) + { + // Read the response status line. The response_ streambuf will + // automatically grow to accommodate the entire line. The growth may be + // limited by passing a maximum size to the streambuf constructor. + boost::asio::async_read_until(socket_, response_, "\r\n", + boost::bind(&client::handle_read_status_line, this, + boost::asio::placeholders::error)); + + std::thread t([=](){ + printf("睡眠5秒后开启定时器\n"); + Sleep(5000); + + // boost::asio::deadline_timer timeer; + printf("开启定时器60秒后发送数据\n"); + this->timeout_check_timer_.expires_from_now(boost::posix_time::seconds(600)); + this->timeout_check_timer_.async_wait([this](const boost::system::error_code& ec) { + if (!ec) { + // LOG_TRACE_ALL("check timout, thread id:%u\n", this_thread()); + printf("定时器就绪!\n"); +#if 0 + //thelib::asy::scoped_rlock guard(rwlock_); + std::ostream request_stream(&request_); + request_stream << "Hello Server!!!\r\n"; + + auto fd = socket_.native_handle(); + boost::asio::async_write(socket_, request_, + boost::bind(&client::handle_write_request_other_thread, this, + boost::asio::placeholders::error)); +#endif + } + }); + }); + t.detach(); + } + else + { + std::cout << "Error: " << err.message() << "\n"; + } + } + + void handle_read_status_line(const boost::system::error_code& err) + { + if (!err) + { + // Check that response is OK. + std::istream response_stream(&response_); + std::string http_version; + response_stream >> http_version; + unsigned int status_code; + response_stream >> status_code; + std::string status_message; + std::getline(response_stream, status_message); + if (!response_stream || http_version.substr(0, 5) != "HTTP/") + { + std::cout << "Invalid response\n"; + return; + } + if (status_code != 200) + { + std::cout << "Response returned with status code "; + std::cout << status_code << "\n"; + return; + } + + // Read the response headers, which are terminated by a blank line. + boost::asio::async_read_until(socket_, response_, "\r\n\r\n", + boost::bind(&client::handle_read_headers, this, + boost::asio::placeholders::error)); + } + else + { + std::cout << "Error: " << err << "\n"; + } + } + + void handle_read_headers(const boost::system::error_code& err) + { + if (!err) + { + // Process the response headers. + std::istream response_stream(&response_); + std::string header; + while (std::getline(response_stream, header) && header != "\r") + std::cout << header << "\n"; + std::cout << "\n"; + + // Write whatever content we already have to output. + if (response_.size() > 0) + std::cout << &response_; + + // Start reading remaining data until EOF. + boost::asio::async_read(socket_, response_, + boost::asio::transfer_at_least(1), + boost::bind(&client::handle_read_content, this, + boost::asio::placeholders::error)); + } + else + { + std::cout << "Error: " << err << "\n"; + } + } + + void handle_read_content(const boost::system::error_code& err) + { + if (!err) + { + // Write all of the data that has been read so far. + std::cout << &response_; + + // Continue reading remaining data until EOF. + boost::asio::async_read(socket_, response_, + boost::asio::transfer_at_least(1), + boost::bind(&client::handle_read_content, this, + boost::asio::placeholders::error)); + } + else if (err != boost::asio::error::eof) + { + std::cout << "Error: " << err << "\n"; + } + } + + tcp::resolver resolver_; + tcp::socket socket_; + boost::asio::streambuf request_; + boost::asio::streambuf response_; +}; + +#if 0 +int main(int argc, char* argv[]) +{ + try + { + if (argc != 3) + { + std::cout << "Usage: async_client \n"; + std::cout << "Example:\n"; + std::cout << " async_client www.boost.org /LICENSE_1_0.txt\n"; + return 1; + } + + boost::asio::io_service io_service; + client c(io_service, argv[1], argv[2]); + io_service.run(); + } + catch (std::exception& e) + { + std::cout << "Exception: " << e.what() << "\n"; + } + + return 0; +} +#endif diff --git a/test/xxsocket_test/http_client.cpp b/test/xxsocket_test/http_client.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b19562853b3a48248f166680be03ec2c43bc757c --- /dev/null +++ b/test/xxsocket_test/http_client.cpp @@ -0,0 +1,328 @@ +// +// async_client.cpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2013-2014 xseekerj +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +//#include +// #include "xxsocket.h" +// using namespace purelib::inet; + +using boost::asio::ip::tcp; + +static boost::asio::io_service io_service; // local io_service on as client + +static void parse_uri(const std::string& uri, std::string& service, std::string& host, u_short& port, std::string& path) +{ + port = 0; + + // Parse host and path from URI + size_t colon = uri.find_first_of(':'); + size_t slash = colon + 3; + size_t port_colon = uri.find_first_of(':', slash); + size_t path_slash = uri.find_first_of('/', slash); + + service = uri.substr(0, colon ); + + if(port_colon == uri.npos) { + host = uri.substr( slash, uri.find_first_of('/',slash) - slash); + } + else { + std::string portS = uri.substr(port_colon + 1); + port = atoi(portS.c_str()); + host = uri.substr( slash, port_colon - slash); + } + + if(path_slash != std::string::npos) { + path = uri.substr( path_slash ); + } + else { + path = "/"; + } +} + +static std::string send_http_req_i(const std::string& host, + u_short port, + const std::string& path = "/", + const std::string& method = "GET", + const std::string& content = "" + ) +{ + try + { + // Get a list of endpoints corresponding to the server name. + tcp::resolver resolver(io_service); + // boost::asio::ip::tcp::resolver::query query("", port); + tcp::resolver::query query(host, "http"); + + tcp::resolver::iterator endpoint_iterator = resolver.resolve(query); + + auto endpoint = endpoint_iterator->endpoint(); + if(port != 0) { + endpoint.port(port); + } + // Try each endpoint until we successfully establish a connection. + // tcp::socket socket(io_service); + boost::asio::ip::tcp::socket socket(io_service); + + socket.open(boost::asio::ip::tcp::v4()); + + + // 设为非阻塞 + // socket.io_control(boost::asio::ip::tcp::socket::non_blocking_io(true)); + //xxsocket::set_nonblocking(socket.native_handle(), true); + //socket.set_verify_callback(boost::asio::ssl::rfc2818_verification("sandbox.itunes.apple.com")); + // socket.connect(endpoint); +#if 0 + timeval tv = {10}; + if(xxsocket::connect_n(socket.native_handle(), endpoint.address().to_string().c_str(), + endpoint.port(), &tv) != 0) + { + return ""; + } +#endif + // boost::asio::connect(socket.lowest_layer(), endpoint_iterator); + // socket.handshake(boost::asio::ssl::stream_base::client); + // Form the request. We specify the "Connection: close" header so that the + // server will close the socket after transmitting the response. This will + // allow us to treat all data up until the EOF as the content. + boost::asio::streambuf request; + std::ostream request_stream(&request); + request_stream << method << " " << path << " HTTP/1.0\r\n"; + request_stream << "Host: " << host << "\r\n"; + request_stream << "Accept: */*\r\n"; + if(method == "POST") { + request_stream << "Content-Type: application/json" << "\r\n"; + request_stream << "Content-Length: " << content.size() << "\r\n"; + request_stream << "Connection: Close\r\n\r\n"; + request_stream << content; + } + else { + request_stream << "Connection: Close\r\n\r\n"; + } + + // Send the request. + size_t bytes_transferred = boost::asio::write(socket, request); + + // Read the response status line. The response streambuf will automatically + // grow to accommodate the entire line. The growth may be limited by passing + // a maximum size to the streambuf constructor. + boost::asio::streambuf response; + boost::asio::read_until(socket, response, "\r\n"); + + // Check that response is OK. + std::istream response_stream(&response); + std::string http_version; + response_stream >> http_version; + unsigned int status_code; + response_stream >> status_code; + std::string status_message; + std::getline(response_stream, status_message); + if (!response_stream || http_version.substr(0, 5) != "HTTP/") + { + std::cout << "Invalid response\n"; + return ""; + } + if (status_code != 200) + { + std::cout << "Response returned with status code " << status_code << "\n"; + return ""; + } + + // Read the response headers, which are terminated by a blank line. + boost::asio::read_until(socket, response, "\r\n\r\n"); + + // Process the response headers. + std::string header; + while (std::getline(response_stream, header) && header != "\r") + std::cout << header << "\n"; + std::cout << "\n"; + + // Write whatever content we already have to output. + // std::size_t n = boost::asio::read_until(sock, sb, '\n'); + boost::asio::streambuf::const_buffers_type bufs = response.data(); + std::string response_data( + boost::asio::buffers_begin(bufs), + boost::asio::buffers_begin(bufs) + response.size()); + + // Read until EOF, writing data to output as we go. + boost::system::error_code error; + + char buffer[512]; + memset(buffer, 0, sizeof(buffer)); + bytes_transferred = 0; + + while((bytes_transferred = + boost::asio::read(socket, boost::asio::buffer(buffer), + boost::asio::transfer_at_least(1), error)) ) + { + response_data.append(buffer, bytes_transferred); + } + + /* while (boost::asio::read(socket, response, + boost::asio::transfer_at_least(1), error)) + ss << &response;*/ + // std::string contentr = ss.str(); + if (error != boost::asio::error::eof) + { // short read, peer already close the connect + // throw boost::system::system_error(error); + std::clog << "Warnning: peer already close the connection.\n"; + } + + return std::move(response_data); + } + catch (std::exception& e) + { + std::cout << "Exception: " << e.what() << "\n"; + return ""; + } +} + +static std::string send_https_req_i(const std::string& host, + u_short port, + const std::string& path = "/", + const std::string& method = "GET", + const std::string& content = "" + ) +{ +#if 0 + try + { + + boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv3); + + // Get a list of endpoints corresponding to the server name. + tcp::resolver resolver(io_service); + tcp::resolver::query query(host, "https"); + tcp::resolver::iterator endpoint_iterator = resolver.resolve(query); + + // Try each endpoint until we successfully establish a connection. + // tcp::socket socket(io_service); + boost::asio::ssl::stream socket(io_service, ctx); + socket.set_verify_mode(boost::asio::ssl::verify_none); + + auto endpoint = endpoint_iterator->endpoint(); + if(port != 0) { + endpoint.port(port); + } + + boost::asio::connect(socket.lowest_layer(), endpoint_iterator); + + socket.handshake(boost::asio::ssl::stream_base::client); + // Form the request. We specify the "Connection: close" header so that the + // server will close the socket after transmitting the response. This will + // allow us to treat all data up until the EOF as the content. + boost::asio::streambuf request; + std::ostream request_stream(&request); + request_stream << method << " " << path << " HTTP/1.0\r\n"; + request_stream << "Host: " << host << "\r\n"; + request_stream << "Accept: */*\r\n"; + if(method == "POST") { + request_stream << "Content-Length: " << content.size() << "\r\n"; + request_stream << "Connection: Close\r\n\r\n"; + request_stream << content; + } + else { + request_stream << "Connection: Close\r\n\r\n"; + } + + // Send the request. + boost::asio::write(socket, request); + + // Read the response status line. The response streambuf will automatically + // grow to accommodate the entire line. The growth may be limited by passing + // a maximum size to the streambuf constructor. + boost::asio::streambuf response_buffer; + boost::asio::read_until(socket, response_buffer, "\r\n"); + + // Read header to check that response is OK. + std::istream response_stream(&response_buffer); + std::string http_version; + response_stream >> http_version; + unsigned int status_code; + response_stream >> status_code; + std::string status_message; + std::getline(response_stream, status_message); + if (!response_stream || http_version.substr(0, 5) != "HTTP/") + { + std::cout << "Invalid response\n"; + return ""; + } + if (status_code != 200) + { + std::cout << "Response returned with status code " << status_code << "\n"; + return ""; + } + + /// Consume all header + boost::asio::read_until(socket, response_buffer, "\r\n\r\n"); + response_buffer.consume(response_buffer.size()); + + // Read body until EOF, writing data to output as we go. + boost::system::error_code error; + + while( (boost::asio::read(socket, response_buffer, boost::asio::transfer_at_least(1), error)) ) + { + ; // response_data.append(buffer, bytes_transferred); + } + + boost::asio::streambuf::const_buffers_type bufs = response_buffer.data(); + return std::string( + boost::asio::buffers_begin(bufs), + boost::asio::buffers_begin(bufs) + response_buffer.size()); + + //if (error != boost::asio::error::eof) + //{ // short read, peer already close the connect + // // throw boost::system::system_error(error); + // std::clog << "Warnning: peer already close the connection.\n"; + //} + //return std::move(response_data); + } + catch (std::exception& e) + { + std::cout << "Exception: " << e.what() << "\n"; + return ""; + } +#endif + return ""; +} + +std::string send_http_req(const std::string& uri, const std::string& method = "POST", const std::string& content = "") +{ + std::string host, service, path; + u_short port = 0; + parse_uri(uri, service, host, port, path); + if(service == "http") { + return send_http_req_i(host, port, path, method, content); + } + else if(service == "https") { + return send_https_req_i(host, port, path, method, content); + } + else { + std::cerr << "Invalid http protocol\n"; + return ""; + } +} + +#if 0 +#ifdef _WIN32 +#pragma comment(lib, "libeay32.lib") +#pragma comment(lib, "ssleay32.lib") +#endif +#endif diff --git a/test/xxsocket_test/http_client.hpp b/test/xxsocket_test/http_client.hpp new file mode 100644 index 0000000000000000000000000000000000000000..08b487d0bd98d00768c142adb4f697f8a27aa860 --- /dev/null +++ b/test/xxsocket_test/http_client.hpp @@ -0,0 +1,8 @@ +#ifndef _HTTP_CLIENT_HPP_ +#define _HTTP_CLIENT_HPP_ +#include + +extern std::string send_http_req(const std::string& uri, const std::string& method = "POST", const std::string& content = ""); + +#endif + diff --git a/test/xxsocket_test/pcode_autog_client_constants.h b/test/xxsocket_test/pcode_autog_client_constants.h index abe475384dced1aba0a4fdf3fcac962015107caf..c9842e1733e113993c3a211e54d711b5cded29fe 100644 --- a/test/xxsocket_test/pcode_autog_client_constants.h +++ b/test/xxsocket_test/pcode_autog_client_constants.h @@ -8,6 +8,9 @@ #define _PCODE_AUTOG_CLIENT_CONSTANTS_H_ enum { + CID_LOGIN_REQ = 101, + CID_LOGIN_RESP = 102, + CID_LOCAL_ERROR_INFO = 0x7fff, CID_MSG_PEER_ENDPOINT_REQ = 1001, CID_MSG_PEER_ENDPOINT_RESP= 1002, CID_MSG_GET_FRIENDLIST_REQ = 1003, diff --git a/test/xxsocket_test/pcode_autog_client_messages.cpp b/test/xxsocket_test/pcode_autog_client_messages.cpp index 9eb9e5e08cc8a3043cc64d2a23c72d304787d57a..92948755afff79b1fb5dc1702cd79ae37507a235 100644 --- a/test/xxsocket_test/pcode_autog_client_messages.cpp +++ b/test/xxsocket_test/pcode_autog_client_messages.cpp @@ -56,6 +56,99 @@ std::string MsgHeader::get_formated_string(void) const return ss.str(); } +obinarystream LoginReq::encode(void) const +{ + /// create message header stream. + auto obs = pcode_autog_begin_encode(CID_LOGIN_REQ); + + /// encode message fields. + obs.write_v(this->username); + obs.write_v(this->password); + return std::move(obs); +} + +int LoginReq::decode(const char* data, int len) +{ + ibinarystream ibs; + ibs.vassign(data, len); + + ibs.read_v(this->username); + ibs.read_v(this->password); + return ibs.remain(); +} + +std::string LoginReq::get_formated_string(void) const +{ + std::stringstream ss; + ss << "LoginReq:\n"; + ss << strfmt("username", this->username << '\n', '-'); + ss << strfmt("password", this->password << '\n', '-'); + return ss.str(); +} + +obinarystream LoginResp::encode(void) const +{ + /// create message header stream. + auto obs = pcode_autog_begin_encode(CID_LOGIN_RESP); + + /// encode message fields. + obs.write_i(this->succeed); + obs.write_i(this->session); + obs.write_v(this->append_info); + return std::move(obs); +} + +int LoginResp::decode(const char* data, int len) +{ + ibinarystream ibs; + ibs.vassign(data, len); + + ibs.read_i(this->succeed); + ibs.read_i(this->session); + ibs.read_v(this->append_info); + return ibs.remain(); +} + +std::string LoginResp::get_formated_string(void) const +{ + std::stringstream ss; + ss << "LoginResp:\n"; + ss << strfmt("succeed", (int)this->succeed << '\n', '-'); + ss << strfmt("session", this->session << '\n', '-'); + ss << strfmt("append_info", this->append_info << '\n', '-'); + return ss.str(); +} + +obinarystream LocalErrorResp::encode(void) const +{ + /// create message header stream. + auto obs = pcode_autog_begin_encode(CID_LOCAL_ERROR_INFO); + + /// encode message fields. + obs.write_i(this->error_code); + obs.write_v(this->error_msg); + return std::move(obs); +} + +int LocalErrorResp::decode(const char* data, int len) +{ + ibinarystream ibs; + ibs.vassign(data, len); + + ibs.read_i(this->error_code); + ibs.read_v(this->error_msg); + return ibs.remain(); +} + +std::string LocalErrorResp::get_formated_string(void) const +{ + std::stringstream ss; + ss << "LocalErrorResp:\n"; + ss << strfmt("error_code", this->error_code << '\n', '-'); + ss << strfmt("error_msg", this->error_msg << '\n', '-'); + return ss.str(); +} + obinarystream MsgPeerEndpointReq::encode(void) const { /// create message header stream. @@ -167,6 +260,9 @@ MsgBase* messages::temp_create_message(int command_id) static int internal_message_ctor_table_preinit(void) { + s_table_message_ctor[CID_LOGIN_REQ]= []()->MsgBase*{ return new(s_allocp) LoginReq(); }; + s_table_message_ctor[CID_LOGIN_RESP]= []()->MsgBase*{ return new(s_allocp) LoginResp(); }; + s_table_message_ctor[CID_LOCAL_ERROR_INFO]= []()->MsgBase*{ return new(s_allocp) LocalErrorResp(); }; s_table_message_ctor[CID_MSG_PEER_ENDPOINT_REQ]= []()->MsgBase*{ return new(s_allocp) MsgPeerEndpointReq(); }; s_table_message_ctor[CID_MSG_PEER_ENDPOINT_RESP]= []()->MsgBase*{ return new(s_allocp) MsgPeerEndpointResp(); }; s_table_message_ctor[CID_MSG_GET_FRIENDLIST_REQ]= []()->MsgBase*{ return new(s_allocp) MsgGetFriendListReq(); }; diff --git a/test/xxsocket_test/pcode_autog_client_messages.h b/test/xxsocket_test/pcode_autog_client_messages.h index 8bd62f1ab77629cf46b63df19da67bd9477d3211..3a2ead85e91b1da961bb4ac4baa3db77f45b89d2 100644 --- a/test/xxsocket_test/pcode_autog_client_messages.h +++ b/test/xxsocket_test/pcode_autog_client_messages.h @@ -42,6 +42,55 @@ struct MsgHeader { std::string get_formated_string(void) const; }; +struct LoginReq : public MsgBase { + std::string username; + std::string password; + + obinarystream encode(void) const override; + + // decode return the remain bytes of buffer. + int decode(const char* data, int len) override; + + int get_id() const override { return CID_LOGIN_REQ; }; + + const char* get_className() const override { return "LoginReq"; }; + + std::string get_formated_string(void) const; +}; + +struct LoginResp : public MsgBase { + bool succeed; + int32_t session; + std::string append_info; + + obinarystream encode(void) const override; + + // decode return the remain bytes of buffer. + int decode(const char* data, int len) override; + + int get_id() const override { return CID_LOGIN_RESP; }; + + const char* get_className() const override { return "LoginResp"; }; + + std::string get_formated_string(void) const; +}; + +struct LocalErrorResp : public MsgBase { + int16_t error_code; + std::string error_msg; + + obinarystream encode(void) const override; + + // decode return the remain bytes of buffer. + int decode(const char* data, int len) override; + + int get_id() const override { return CID_LOCAL_ERROR_INFO; }; + + const char* get_className() const override { return "LocalErrorResp"; }; + + std::string get_formated_string(void) const; +}; + struct MsgPeerEndpointReq : public MsgBase { uint32_t user_id; diff --git a/test/xxsocket_test/sendmail.cpp b/test/xxsocket_test/sendmail.cpp new file mode 100644 index 0000000000000000000000000000000000000000..efa1290202208fc41262341a0bafc86b9fd5dcb2 --- /dev/null +++ b/test/xxsocket_test/sendmail.cpp @@ -0,0 +1,554 @@ +#include "xxsocket.h" +#include "timestamp.h" +#include "nsconv.h" +// #include +#include +#include +#include "libb64.h" + +//#include "cocos2d.h" +//#include "HttpClient.h" +//#include "detail/VXToolHal.h" +//#include "purelib/utils/crypto_wrapper.h" +// +//USING_NS_CC; +//using namespace cocos2d::network; +#include + +const unsigned char Base64ValTab[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +#ifndef _WIN32 +#define BYTE unsigned char +#endif +#define AVal(x) Base64ValTab[x] + +//#pragma comment (lib,"ws2_32.lib") +using namespace purelib; +using namespace purelib::inet; + +static uint8_t hex2uchr(const uint8_t hex) +{ + return hex > 9 ? (hex - 10 + 'A') : (hex + '0'); +} + +static std::string urlencode(const std::string& input) +{ + std::string output; + for (size_t ix = 0; ix < input.size(); ix++) + { + uint8_t buf[4]; + memset(buf, 0, 4); + if (isalnum((uint8_t)input[ix])) + { + buf[0] = input[ix]; + } + else if ( isspace((uint8_t)input[ix] ) ) + { + buf[0] = '+'; + } + else + { + buf[0] = '%'; + buf[1] = ::hex2uchr((uint8_t)input[ix] >> 4); + buf[2] = ::hex2uchr((uint8_t)input[ix] % 16); + } + output += (char *)buf; + } + return std::move(output); +}; + +#if 0 +//获取系统版本 +BOOL internalGetOSName(CString& csOsName) +{ + OSVERSIONINFOEX osvi; + SYSTEM_INFO si; + BOOL bOsVersionInfoEx; + ZeroMemory(&si, sizeof(SYSTEM_INFO)); + ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); + + // Try calling GetVersionEx using the OSVERSIONINFOEX structure. + // If that fails, try using the OSVERSIONINFO structure. + + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + + bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO *)&osvi); + if (!bOsVersionInfoEx) + { + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + if (!GetVersionEx((OSVERSIONINFO *)&osvi)) + return FALSE; + } + + // Call GetNativeSystemInfo if supported + // or GetSystemInfo otherwise. + else GetSystemInfo(&si); + + switch (osvi.dwPlatformId) + { + // Test for the Windows NT product family. + + case VER_PLATFORM_WIN32_NT: + + if (osvi.dwMajorVersion == 10 && osvi.dwMinorVersion == 0) + { + csOsName += _T("Windows 10 "); + } + + if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 3) + { + csOsName += _T("Windows 8.1 "); + } + + if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 2) + { + csOsName += _T("Windows 8 "); + } + + if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 1) + { + csOsName += _T("Windows 7 "); + } + + // Test for the specific product. + if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0) + { + if (osvi.wProductType == VER_NT_WORKSTATION) + { + csOsName += _T("Windows Vista "); + } + else + { + csOsName += _T("Windows Server \"Longhorn\" "); + } + } + + if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) + { + if (osvi.wProductType == VER_NT_WORKSTATION && + si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) + { + csOsName += _T("Microsoft Windows XP Professional x64 Edition "); + } + else + { + csOsName += _T("Microsoft Windows Server 2003, "); + } + } + + if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) + { + csOsName += _T("Microsoft Windows XP "); + } + + if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) + { + csOsName += _T("Microsoft Windows 2000 "); + } + + if (osvi.dwMajorVersion <= 4) + { + csOsName += _T("Microsoft Windows NT "); + } + + // Test for specific product on Windows NT 4.0 SP6 and later. + if (bOsVersionInfoEx) + { + // Test for the workstation type. + if (osvi.wProductType == VER_NT_WORKSTATION && + si.wProcessorArchitecture != PROCESSOR_ARCHITECTURE_AMD64) + { + if (osvi.dwMajorVersion == 4) + { + csOsName += _T("Workstation 4.0 "); + } + else if (osvi.wSuiteMask & VER_SUITE_PERSONAL) + { + csOsName += _T("Home Edition "); + } + else + { + csOsName += _T("Professional "); + } + } + + // Test for the server type. + else if (osvi.wProductType == VER_NT_SERVER || + osvi.wProductType == VER_NT_DOMAIN_CONTROLLER) + { + if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) + { + if (si.wProcessorArchitecture == + PROCESSOR_ARCHITECTURE_IA64) + { + if (osvi.wSuiteMask & VER_SUITE_DATACENTER) + { + csOsName += _T("Datacenter Edition for Itanium-based Systems"); + } + else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) + { + csOsName += _T("Enterprise Edition for Itanium-based Systems"); + } + } + + else if (si.wProcessorArchitecture == + PROCESSOR_ARCHITECTURE_AMD64) + { + if (osvi.wSuiteMask & VER_SUITE_DATACENTER) + { + csOsName += _T("Datacenter x64 Edition "); + } + else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) + { + + } + else + { + csOsName += _T("Standard x64 Edition "); + } + } + else + { + if (osvi.wSuiteMask & VER_SUITE_DATACENTER) + { + csOsName += _T("Datacenter Edition "); + } + else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) + { + csOsName += _T("Enterprise Edition "); + } + else if (osvi.wSuiteMask & VER_SUITE_BLADE) + { + csOsName += _T("Web Edition "); + } + else + { + csOsName += _T("Standard Edition "); + } + } + } + else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) + { + if (osvi.wSuiteMask & VER_SUITE_DATACENTER) + { + csOsName += _T("Datacenter Server "); + } + else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) + { + csOsName += _T("Advanced Server "); + } + else + { + csOsName += _T("Server "); + } + } + else // Windows NT 4.0 + { + if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) + { + csOsName += _T("Server 4.0, Enterprise Edition "); + } + else + { + csOsName += _T("Server 4.0 "); + } + } + } + } + // Test for specific product on Windows NT 4.0 SP5 and earlier + else + { + HKEY hKey; + TCHAR szProductType[256]; + DWORD dwBufLen = 256 * sizeof(TCHAR); + LONG lRet; + + lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, + _T("SYSTEM\\CurrentControlSet\\Control\\ProductOptions"), + 0, KEY_QUERY_VALUE, &hKey); + if (lRet != ERROR_SUCCESS) + return FALSE; + + lRet = RegQueryValueEx(hKey, TEXT("ProductType"), + NULL, NULL, (LPBYTE)szProductType, &dwBufLen); + RegCloseKey(hKey); + + if ((lRet != ERROR_SUCCESS) || + (dwBufLen > 256 * sizeof(TCHAR))) + return FALSE; + + if (lstrcmpi(TEXT("WINNT"), szProductType) == 0) + { + csOsName += _T("Workstation "); + } + if (lstrcmpi(TEXT("LANMANNT"), szProductType) == 0) + { + csOsName += _T("Server "); + } + if (lstrcmpi(TEXT("SERVERNT"), szProductType) == 0) + { + csOsName += _T("Advanced Server "); + } + CString cstmp; + cstmp.Format(_T("%d.%d "), osvi.dwMajorVersion, osvi.dwMinorVersion); + csOsName += cstmp; + } + + // Display service pack (if any) and build number. + + if (osvi.dwMajorVersion == 4 && + lstrcmpi(osvi.szCSDVersion, TEXT("Service Pack 6")) == 0) + { + HKEY hKey; + LONG lRet; + + // Test for SP6 versus SP6a. + lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, + _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Hotfix\\Q246009"), + 0, KEY_QUERY_VALUE, &hKey); + if (lRet == ERROR_SUCCESS) + { + CString cstmp; + cstmp.Format(_T("Service Pack 6a (Build %d)"), osvi.dwBuildNumber & 0xFFFF); + csOsName += cstmp; + } + else // Windows NT 4.0 prior to SP6a + { + CString cstmp; + cstmp.Format(_T("%s (Build %d)"), osvi.szCSDVersion, osvi.dwBuildNumber & 0xFFFF); + csOsName += cstmp; + } + RegCloseKey(hKey); + } + else // not Windows NT 4.0 + { + CString cstmp; + cstmp.Format(_T("%s (Build %d)"), osvi.szCSDVersion, osvi.dwBuildNumber & 0xFFFF); + csOsName += cstmp; + } + + break; + + // Test for the Windows Me/98/95. + case VER_PLATFORM_WIN32_WINDOWS: + + if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0) + { + csOsName += _T("Microsoft Windows 95 "); + if (osvi.szCSDVersion[1] == 'C' || osvi.szCSDVersion[1] == 'B') + { + csOsName += _T("OSR2 "); + } + } + + if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10) + { + csOsName += _T("Microsoft Windows 98 "); + if (osvi.szCSDVersion[1] == 'A' || osvi.szCSDVersion[1] == 'B') + { + csOsName += _T("SE "); + } + } + + if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90) + { + csOsName += _T("Microsoft Windows Millennium Edition"); + } + break; + + case VER_PLATFORM_WIN32s: + + csOsName += _T("Microsoft Win32s\n"); + break; + } + return TRUE; +} +#endif + +// smtp send mail, could not use +#if 0 +void printRecv(xxsocket& s) +{ + char recvBuff[1024*8]; + memset(recvBuff,0,sizeof(recvBuff)); + + //xxsocket s(sock); + s.recv_i(recvBuff,1000); + // s.release(); + OutputDebugStringA(recvBuff); + OutputDebugStringA("\n"); +} + +int EncodingBase64(const char * pInput, int ilen, char * pOutput) +{ + memset(pOutput, 0x0, strlen(pOutput)); + // std::string ciphertext((plaintext.length() * 2), '\0'); + char* wrptr = pOutput; + base64_encodestate state; + base64_init_encodestate(&state); + int r1 = base64_encode_block(pInput, ilen, wrptr, &state); + int r2 = base64_encode_blockend(wrptr + r1, &state); + + return (r1 + r2); +} + +enum SendResult {errorusername,ok}; + +int smtp_sendmail(const char * smtpServer,int port, const char* username, const char * password,const char* from, const char * to, const char * subject,const char * body) +{ + xxsocket tcpcli; + if (tcpcli.xpconnect_n(smtpServer, port, 3.0f) != 0) + return errorusername; + + int n = 0; + + char* buffer = new char[SZ(16, k)]; + memset(buffer, 0x0, SZ(16, k)); + + n = sprintf(buffer,"EHLO %s\r\n",from);//from为char数据。存储发送地址 + tcpcli.send(buffer, n); + + printRecv(tcpcli); + + n = sprintf(buffer,"AUTH LOGIN\r\n"); + tcpcli.send(buffer, n); + + printRecv(tcpcli); + + //USER NAME + //User name is coded by base64. + EncodingBase64(username, strlen(username), buffer);//先将用户帐号经过base64编码 + strcat(buffer,"\r\n"); + tcpcli.send(buffer,strlen(buffer)); + + printRecv(tcpcli); + + //password coded by base64 + EncodingBase64(password, strlen(password), buffer);//先将密码经过base64编码 + strcat(buffer,"\r\n"); + tcpcli.send(buffer,strlen(buffer)); + + printRecv(tcpcli); + + + n = sprintf(buffer,"MAIL FROM:<%s>\r\n",from); + tcpcli.send(buffer, n); + + printRecv(tcpcli); + + n = sprintf(buffer,"RCPT TO:<%s>\r\n",to); + tcpcli.send(buffer, n); + + printRecv(tcpcli); + + //memset(buffer,0,sizeof(buffer)); + n = sprintf(buffer,"DATA\r\n"); + tcpcli.send(buffer, n); + printRecv(tcpcli); + + //DATA head + n = sprintf(buffer,"Subject:%s\r\n\r\n",subject); + + tcpcli.send(buffer, n); + + n = sprintf(buffer,"%s\r\n.\r\n",body); + //DATA body + tcpcli.send(buffer, n); + printRecv(tcpcli); + + strcpy(buffer,"QUIT\r\n"); + tcpcli.send(buffer,strlen(buffer)); + printRecv(tcpcli); + + tcpcli.shutdown(); + tcpcli.close(); + return ok; +} +#endif + +void http_sendemail(const std::string& mailto, const std::string& subject, std::string&& message) +{ + nsc::replace(message, "\r\n", "
"); + nsc::replace(message, "\n", "
"); + + // post data + std::stringstream datass; + datass << "_token=6OU2b4P2Mad8udXN2pTKU56Q0hF7jASrroZVXGMy" + << "&emailTo=" << mailto + << "&replyTo=" + << "&subject=" << subject + << "&message=" << urlencode(message); + + auto data = datass.str(); + + // construct http package: Internet Explorer 11(11.51.14393.0 Update: 11.0.34(KB3175443) Windows 10(10.0.14393.82) + std::stringstream ss; + ss << "POST /send HTTP/1.1\r\n"; + ss << "Content-Type: application/x-www-form-urlencoded; charset=UTF-8\r\n"; + ss << "Accept: application/json, text/javascript, */*; q=0.01\r\n"; + ss << "X-Requested-With: XMLHttpRequest\r\n"; + ss << "Referer: http://send-email.org/\r\n"; + ss << "Accept-Language: zh-Hans-CN,zh-Hans;q=0.8,en-US;q=0.5,en;q=0.3\r\n"; + ss << "Accept-Encoding: gzip, deflate\r\n"; + // Chrome, Internet Explorer 11 is: User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko\r\n + // ss << "User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36\r\n"; + ss << "User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko\r\n"; + ss << "Host: send-email.org\r\n"; + ss << "Content-Length: " << data.size() << "\r\n"; + ss << "DNT: 1\r\n"; + ss << "Connection: Keep-Alive\r\n"; // Close + ss << "Cache-Control: no-cache\r\n"; + ss << "Cookie: _ga=GA1.2.1544911637.1471488460; _gat=1\r\n"; + // ss << "Origin: http://send-email.org\r\n"; + ss << "\r\n"; + + ss << data; + + auto requestData = ss.str(); + + xxsocket httpcli; + if (httpcli.xpconnect_n("send-email.org", 80, 5) != 0) + { + OutputDebugString(L"connect send-email.org failed!\n"); + return; + } + + if (httpcli.send_n(requestData.c_str(), requestData.size(), 5) <= 0) + { + OutputDebugString(L"send request to send-email.org failed!\n"); + return; + } + + std::string responseData; + if (!httpcli.read_until(responseData, "\r\n\r\n", 4)) + { + OutputDebugString(L"recv response from send-email.org failed!\n"); + return; + } + + responseData.push_back('\n'); + OutputDebugStringA("response data:"); + OutputDebugStringA(responseData.c_str()); + + Sleep(2000); + httpcli.shutdown(); + httpcli.close(); +} + +#if 0 +void submit_crash_log(const char* content) +{ + CString osName; + internalGetOSName(osName); + osName.Append(_T(":\n")); + + std::string platformInfo = purelib::nsc::transcode(osName.GetString()); + extern std::string g_infoGPU; + platformInfo.append(g_infoGPU); + platformInfo.append(":\n"); + +#if 0 + sendmail(ctimestamp(), (platformInfo + content)); +#else +#endif +} +#endif diff --git a/test/xxsocket_test/xxsocket_test-vc14.vcxproj b/test/xxsocket_test/xxsocket_test-vc14.vcxproj index d9f9ed86a76889fdd805b05fda679f726f6df999..17cf377234a2db52f66cd9a11468ab4677ff4b66 100644 --- a/test/xxsocket_test/xxsocket_test-vc14.vcxproj +++ b/test/xxsocket_test/xxsocket_test-vc14.vcxproj @@ -22,7 +22,8 @@ {5D0F6B61-954B-45ED-B3AD-21B5BF077666} Win32Proj xxsocket_test-vc14 - 8.1 + + @@ -41,7 +42,7 @@ Application true - v140_xp + v140 Unicode @@ -87,8 +88,8 @@ Level3 Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - ..\..\src + WIN32;_DEBUG;_CONSOLE;BOOST_ERROR_CODE_HEADER_ONLY;BOOST_SYSTEM_NO_DEPRECATED;BOOST_SYSTEM_NO_LIB;BOOST_DATE_TIME_NO_LIB;BOOST_REGEX_NO_LIB;%(PreprocessorDefinitions) + ..\..\src;..\..\refs\boost.asio\ Console @@ -101,8 +102,8 @@ Level3 Disabled - _DEBUG;_CONSOLE;%(PreprocessorDefinitions) - ..\..\src + _DEBUG;_CONSOLE;BOOST_ERROR_CODE_HEADER_ONLY;BOOST_SYSTEM_NO_DEPRECATED;BOOST_SYSTEM_NO_LIB;BOOST_DATE_TIME_NO_LIB;BOOST_REGEX_NO_LIB;BOOST_ASIO_DISABLE_IOCP;%(PreprocessorDefinitions) + ..\..\src;..\..\refs\boost.asio Console @@ -117,8 +118,8 @@ MaxSpeed true true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - ..\..\src + WIN32;NDEBUG;_CONSOLE;BOOST_ERROR_CODE_HEADER_ONLY;BOOST_SYSTEM_NO_DEPRECATED;BOOST_SYSTEM_NO_LIB;BOOST_DATE_TIME_NO_LIB;BOOST_REGEX_NO_LIB;BOOST_ASIO_DISABLE_THREADS;_WIN32_WINNT=0x0a00;BOOST_ASIO_ENABLE_BUFFER_DEBUGGING;%(PreprocessorDefinitions) + ..\..\src;..\..\refs\boost.asio\ Console @@ -146,25 +147,38 @@ + + - + + + + + + + - + + + + + + diff --git a/test/xxsocket_test/xxsocket_test-vc14.vcxproj.filters b/test/xxsocket_test/xxsocket_test-vc14.vcxproj.filters index 9b60480c769c1da7505e65e2f97a46beeff11a35..09af72175f7043f979d6a7a4539f60077698eb35 100644 --- a/test/xxsocket_test/xxsocket_test-vc14.vcxproj.filters +++ b/test/xxsocket_test/xxsocket_test-vc14.vcxproj.filters @@ -16,20 +16,17 @@ {39c57de0-8673-419c-b036-ef9cff8275e2} + + {a2c256b0-b7b7-4a2d-8321-80b2df80fac5} + - - Source Files - lib lib - - lib - Source Files @@ -39,6 +36,21 @@ lib + + lib + + + lib + + + Source Files + + + Source Files + + + lib + @@ -47,9 +59,6 @@ lib - - lib - Source Files @@ -68,5 +77,34 @@ lib + + lib + + + lib + + + lib\interrupter + + + lib\interrupter + + + lib\interrupter + + + lib\interrupter + + + + + lib\interrupter + + + lib\interrupter + + + lib\interrupter + \ No newline at end of file diff --git a/test/xxsocket_test/xxsocket_test-vc14.vcxproj.user b/test/xxsocket_test/xxsocket_test-vc14.vcxproj.user new file mode 100644 index 0000000000000000000000000000000000000000..7c9eb00214d7c43c2b2c8470f95333386a2595aa --- /dev/null +++ b/test/xxsocket_test/xxsocket_test-vc14.vcxproj.user @@ -0,0 +1,11 @@ +锘 + + + www.boost.org /LICENSE_1_0.txt + WindowsLocalDebugger + + + https://127.0.0.1 /test.txt + WindowsLocalDebugger + + \ No newline at end of file diff --git a/test/xxsocket_test/xxsocket_test.cpp b/test/xxsocket_test/xxsocket_test.cpp index 9663673b56f0aead32e17945c18ee07a19cdac5a..015579c40c5bf9328b0b440b8b66fe4a470b9781 100644 --- a/test/xxsocket_test/xxsocket_test.cpp +++ b/test/xxsocket_test/xxsocket_test.cpp @@ -1,11 +1,22 @@ #include "xxsocket.h" +#include "async_tcp_client.h" #include "pcode_autog_client_messages.h" +#include "http_client.hpp" + +#if defined(_WIN32) +#define sleep(sec) Sleep(sec * 1000) +#define msleep(msec) Sleep(msec) +#endif using namespace purelib::inet; -static const int sinlen = sizeof(sockaddr_in); -static const int sinlen2 = 0x10; +////////////////////////////////////////////// +// async_tcp_client: 业务无关的基于tcp的二进制协议服务 +// 以下为必须接口,仅展现用法, 建议封装成一个业务单例,例如NetworManager +#define PACKET_HEADER_LENGTH sizeof(messages::MsgHeader) +#define PACKET_MAGIC_NUMBER 0x5a5a +// 消息包头, 必须实现, 字段可选,但至少应该有表示协议包长度的字段 obinarystream pcode_autog_begin_encode(uint16_t command_id) { messages::MsgHeader hdr; @@ -17,16 +28,130 @@ obinarystream pcode_autog_begin_encode(uint16_t command_id) return hdr.encode(); } +#if 1 +// 解析消息长度 +bool decode_pdu_length(const char* data, size_t datalen, int& len) +{ + if (datalen >= PACKET_HEADER_LENGTH) { + + char hdrs[PACKET_HEADER_LENGTH]; + + messages::MsgHeader hdr; + hdr.decode(hdrs, sizeof(hdrs)); + + len = hdr.length + PACKET_HEADER_LENGTH; + return true;// PACKET_MAGIC_NUMBER == hdr.reserved; + } + else { + len = -1; + return true; + } +} + +// 如果连接出错,发送超时,构造本地回环错误包 +std::vector build_error_msg(int errorcode, const char* errormsg) +{ + messages::LocalErrorResp error; + error.error_code = errorcode; + error.error_msg = errormsg; + auto msg = error.encode(); + return msg.move(); +} + +// 收到完整的一个消息包, 可用于编解码 +void on_recv_msg(std::vector&& data) +{ + messages::MsgHeader hdr; + int offset = hdr.decode(data.data(), data.size()); + auto msg = messages::temp_create_message(hdr.command_id); + switch (msg->get_id()) + { // + case CID_LOCAL_ERROR_INFO: + printf("网络出错,需要重连!\n"); + break; + case CID_LOGIN_RESP: { + auto detail = dynamic_cast(msg); + printf("登陆%s\n", detail->succeed ? "成功" : "失败"); + tcpcli->close(); // 关闭网络 + + if (detail->succeed) { + // 切换到游戏服务器 + printf("正在连接游戏服务器...\n"); + tcpcli->set_endpoint("192.168.199.246", "", 20001); + tcpcli->notify_connect(); + } + ; } + break; + } +} + +void test_tcp_service() +{ + tcpcli->set_connect_listener([](bool succeed, int error) { + if (succeed) + { // 连接成功, 则可发起登陆协议,这里 +#if 0 + messages::LoginReq req; + req.username = "helloworld"; + req.password = "helloworld"; + auto obs = req.encode(); + tcpcli->async_send(obs.move(), [](ErrorCode error) { + if (error == 0) { // 发送成功 + + } + else { // 可能发送超时, 可能网络出错 + + } + }); +#endif + auto timer = std::shared_ptr(new deadline_timer()); + timer->expires_from_now(std::chrono::seconds(3), true); + timer->async_wait([](bool cancelled) { + if (!cancelled) { + printf("循环定时器,每3秒触发一次.\n"); +#if 1 + std::vector msg; + msg.resize(sizeof("hello world\r\n")); + memcpy(&msg.front(), "hello world\r\n", sizeof("hello world\r\n") - 1); + tcpcli->async_send(std::move(msg)); +#endif + } + }); + } + }); + tcpcli->set_callbacks(decode_pdu_length, build_error_msg, on_recv_msg, [](const vdcallback_t& callb) { + callb(); + }); + tcpcli->set_endpoint("127.0.0.1", "", 80); // 先设置为登陆服务器 + tcpcli->start_service(); + auto start = std::chrono::steady_clock::now(); + printf("3秒后开始连接服务器...\n"); + bool notify = false; + while (1) { + + // bool received = tcpcli->collect_received_pdu(); + //if (!received) { + msleep(1); // 模拟cocos2d-x主线程 + //} + + if (!notify) + { + tcpcli->notify_connect(); + notify = true; + } + } +} + void test_https_connect() { - xxsocket tcpcli; - auto epv6 = xxsocket::resolve("www.baidu.com", 443); - tcpcli.open(epv6.af()); - auto flag = tcpcli.getipsv(); + xxsocket client; + // auto epv6 = xxsocket::resolve("www.baidu.com", 443); + int n = client.xpconnect_n("127.0.0.1", 6001, 3); + auto flag = client.getipsv(); printf("ip protocol support flag is:%d\n", flag); - if (tcpcli.connect_n(epv6, 3/* connect timeout: 3 seconds*/) == 0) + if (n == 0) { - printf("connect https server success."); + printf("connect https server success, [%s] --> [%s]", client.local_endpoint().to_string().c_str(), client.peer_endpoint().to_string().c_str()); } else { printf("connect failed, code:%d,info:%s", xxsocket::get_last_errno(), xxsocket::get_error_msg(xxsocket::get_last_errno())); @@ -35,7 +160,18 @@ void test_https_connect() int main(int, char**) { - test_https_connect(); + // std::string respData = send_http_req("http://x-studio365.com"); + + extern void http_sendemail(const std::string& mailto, const std::string& subject, std::string&& message); + + // 163 mail always response: 554 DT:SPM 163 smtp14,EsCowACH_vF0S7VXPsvDCg--.19895S2 1471499125,... + int smtp_sendmail(const char * smtpServer, int port, const char* username, const char * password, const char* from, const char * to, const char * subject, const char * body); + + // could send 5 mails per hour + http_sendemail("88888888@qq.com", "ckkjgj", "gfjjihuijwiofoiw\ngfkjkghd whitespace new 20160818 12:08,"); + + // test_https_connect(); + test_tcp_service(); getchar(); @@ -44,3 +180,4 @@ int main(int, char**) return 0; } +#endif diff --git a/tools/pcode_autog.exe b/tools/pcode_autog.exe index 71a2bc53bc909c1b76f2ad5e63f46b50cd1723c6..891dc5de532b9e03f3d518a2b009f58db7188fd1 100644 Binary files a/tools/pcode_autog.exe and b/tools/pcode_autog.exe differ diff --git a/tools/pcode_autog_client_constants.lua b/tools/pcode_autog_client_constants.lua new file mode 100644 index 0000000000000000000000000000000000000000..035314c9552f48f92f0472b5f955a1a253bd174c --- /dev/null +++ b/tools/pcode_autog_client_constants.lua @@ -0,0 +1,16 @@ +-- This file is generated by pcode_autog-1.16.6 +-- Copyright(c) HALX99, ALL RIGHTS RESERVED. +-- +-- Purpose: contains some constants defininations +-- +-- +pcode_autog = pcode_autog or {} + +pcode_autog.CID_LOGIN_REQ = 101; +pcode_autog.CID_LOGIN_RESP = 102; +pcode_autog.CID_LOCAL_ERROR_INFO = 0x7fff; +pcode_autog.CID_MSG_PEER_ENDPOINT_REQ = 1001; +pcode_autog.CID_MSG_PEER_ENDPOINT_RESP= 1002; +pcode_autog.CID_MSG_GET_FRIENDLIST_REQ = 1003; +pcode_autog.CID_MSG_GET_FRIENDLIST_RESP = 1004; + diff --git a/tools/protocol.xml b/tools/protocol.xml index 181559f815a6553040927c11475c05aa3e2939d4..e9eb71d2c4e81ecf695f1d6abb48db934b22590e 100644 --- a/tools/protocol.xml +++ b/tools/protocol.xml @@ -63,6 +63,24 @@ obinarystream pcode_autog_begin_encode(uint16_t command_id) + + + + + + + + + + + + + + + + + +