mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
Squashed 'src/beast/' content from commit 43e6d34
git-subtree-dir: src/beast
git-subtree-split: 43e6d345e4
This commit is contained in:
12
.gitattributes
vendored
Normal file
12
.gitattributes
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
# Set default behaviour, in case users don't have core.autocrlf set.
|
||||
* text=auto
|
||||
|
||||
# Github
|
||||
.md text eol=lf
|
||||
|
||||
# Visual Studio
|
||||
*.sln text eol=crlf
|
||||
*.vcproj text eol=crlf
|
||||
*.vcxproj text eol=crlf
|
||||
*.props text eol=crlf
|
||||
*.filters text eol=crlf
|
||||
26
.gitignore
vendored
Normal file
26
.gitignore
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
Docs
|
||||
._*
|
||||
*.mode1v3
|
||||
*.pbxuser
|
||||
*.perspectivev3
|
||||
*.user
|
||||
*.ncb
|
||||
*.suo
|
||||
*.obj
|
||||
*.ilk
|
||||
*.pch
|
||||
*.pdb
|
||||
*.dep
|
||||
*.idb
|
||||
*.manifest
|
||||
*.manifest.res
|
||||
*.o
|
||||
*.d
|
||||
*.sdf
|
||||
xcuserdata
|
||||
contents.xcworkspacedata
|
||||
.DS_Store
|
||||
.svn
|
||||
profile
|
||||
Builds/VisualStudio2012/Debug
|
||||
Builds/VisualStudio2012/Release
|
||||
16
Builds/VisualStudio2012/Beast.props
Normal file
16
Builds/VisualStudio2012/Beast.props
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ImportGroup Label="PropertySheets" />
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup />
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<PreprocessorDefinitions>_CRTDBG_MAP_ALLOC;_WIN32_WINNT=0x0600;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup />
|
||||
</Project>
|
||||
161
Builds/VisualStudio2012/BeastConfig.h
Normal file
161
Builds/VisualStudio2012/BeastConfig.h
Normal file
@@ -0,0 +1,161 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_BEASTCONFIG_H_INCLUDED
|
||||
#define BEAST_BEASTCONFIG_H_INCLUDED
|
||||
|
||||
/** Configuration file for Beast.
|
||||
This sets various configurable options for Beast. In order to compile you
|
||||
must place a copy of this file in a location where your build environment
|
||||
can find it, and then customize its contents to suit your needs.
|
||||
@file BeastConfig.h
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Diagnostics
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Config: BEAST_FORCE_DEBUG
|
||||
Normally, BEAST_DEBUG is set to 1 or 0 based on compiler and project
|
||||
settings, but if you define this value, you can override this to force it
|
||||
to be true or false.
|
||||
*/
|
||||
#ifndef BEAST_FORCE_DEBUG
|
||||
//#define BEAST_FORCE_DEBUG 1
|
||||
#endif
|
||||
|
||||
/** Config: BEAST_LOG_ASSERTIONS
|
||||
If this flag is enabled, the the bassert and bassertfalse macros will always
|
||||
use Logger::writeToLog() to write a message when an assertion happens.
|
||||
Enabling it will also leave this turned on in release builds. When it's
|
||||
disabled, however, the bassert and bassertfalse macros will not be compiled
|
||||
in a release build.
|
||||
@see bassert, bassertfalse, Logger
|
||||
*/
|
||||
#ifndef BEAST_LOG_ASSERTIONS
|
||||
//#define BEAST_LOG_ASSERTIONS 1
|
||||
#endif
|
||||
|
||||
/** Config: BEAST_CHECK_MEMORY_LEAKS
|
||||
Enables a memory-leak check for certain objects when the app terminates.
|
||||
See the LeakChecked class for more details about enabling leak checking for
|
||||
specific classes.
|
||||
*/
|
||||
#ifndef BEAST_CHECK_MEMORY_LEAKS
|
||||
//#define BEAST_CHECK_MEMORY_LEAKS 0
|
||||
#endif
|
||||
|
||||
/** Config: BEAST_COMPILER_CHECKS_SOCKET_OVERRIDES
|
||||
Setting this option makes Socket-derived classes generate compile errors
|
||||
if they forget any of the virtual overrides As some Socket-derived classes
|
||||
intentionally omit member functions that are not applicable, this macro
|
||||
should only be enabled temporarily when writing your own Socket-derived
|
||||
class, to make sure that the function signatures match as expected.
|
||||
*/
|
||||
#ifndef BEAST_COMPILER_CHECKS_SOCKET_OVERRIDES
|
||||
//#define BEAST_COMPILER_CHECKS_SOCKET_OVERRIDES 1
|
||||
#endif
|
||||
|
||||
/** Config: BEAST_CATCH_UNHANDLED_EXCEPTIONS
|
||||
This will wrap thread entry points with an exception catching block.
|
||||
A customizable hook is provided to get called when unhandled exceptions
|
||||
are thrown.
|
||||
@see ProtectedCall
|
||||
*/
|
||||
#ifndef BEAST_CATCH_UNHANDLED_EXCEPTIONS
|
||||
//#define BEAST_CATCH_UNHANDLED_EXCEPTIONS 1
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Libraries
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Config: BEAST_DISABLE_BEAST_VERSION_PRINTING
|
||||
Turns off the debugging display of the beast version number
|
||||
*/
|
||||
#ifndef BEAST_DISABLE_BEAST_VERSION_PRINTING
|
||||
//#define BEAST_DISABLE_BEAST_VERSION_PRINTING 1
|
||||
#endif
|
||||
|
||||
/** Config: BEAST_DONT_AUTOLINK_TO_WIN32_LIBRARIES
|
||||
In a Visual C++ build, this can be used to stop the required system libs
|
||||
being automatically added to the link stage.
|
||||
*/
|
||||
#ifndef BEAST_DONT_AUTOLINK_TO_WIN32_LIBRARIES
|
||||
//#define BEAST_DONT_AUTOLINK_TO_WIN32_LIBRARIES 1
|
||||
#endif
|
||||
|
||||
/** Config: BEAST_INCLUDE_ZLIB_CODE
|
||||
This can be used to disable Beast's embedded 3rd-party zlib code.
|
||||
You might need to tweak this if you're linking to an external zlib library
|
||||
in your app, but for normal apps, this option should be left alone.
|
||||
|
||||
If you disable this, you might also want to set a value for
|
||||
BEAST_ZLIB_INCLUDE_PATH, to specify the path where your zlib headers live.
|
||||
*/
|
||||
#ifndef BEAST_INCLUDE_ZLIB_CODE
|
||||
//#define BEAST_INCLUDE_ZLIB_CODE 1
|
||||
#endif
|
||||
|
||||
/** Config: BEAST_ZLIB_INCLUDE_PATH
|
||||
This is included when BEAST_INCLUDE_ZLIB_CODE is set to zero.
|
||||
*/
|
||||
#ifndef BEAST_ZLIB_INCLUDE_PATH
|
||||
#define BEAST_ZLIB_INCLUDE_PATH <zlib.h>
|
||||
#endif
|
||||
|
||||
/** Config: BEAST_FUNCTIONAL_USES_###
|
||||
<functional> source configuration.
|
||||
Set one of these to manually force a particular implementation of bind().
|
||||
If nothing is chosen then beast will use whatever is appropriate for your
|
||||
environment based on what is available.
|
||||
If you override these, set ONE to 1 and the rest to 0
|
||||
*/
|
||||
#ifndef BEAST_FUNCTIONAL_USES_STD
|
||||
//#define BEAST_FUNCTIONAL_USES_STD 0
|
||||
#endif
|
||||
#ifndef BEAST_FUNCTIONAL_USES_TR1
|
||||
//#define BEAST_FUNCTIONAL_USES_TR1 0
|
||||
#endif
|
||||
#ifndef BEAST_FUNCTIONAL_USES_BOOST
|
||||
//#define BEAST_FUNCTIONAL_USES_BOOST 0
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Boost
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Config: BEAST_USE_BOOST_FEATURES
|
||||
This activates boost specific features and improvements. If this is
|
||||
turned on, the include paths for your build environment must be set
|
||||
correctly to find the boost headers.
|
||||
*/
|
||||
#ifndef BEAST_USE_BOOST_FEATURES
|
||||
//#define BEAST_USE_BOOST_FEATURES 1
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#endif
|
||||
1464
Builds/VisualStudio2012/beast.vcxproj
Normal file
1464
Builds/VisualStudio2012/beast.vcxproj
Normal file
File diff suppressed because it is too large
Load Diff
1550
Builds/VisualStudio2012/beast.vcxproj.filters
Normal file
1550
Builds/VisualStudio2012/beast.vcxproj.filters
Normal file
File diff suppressed because it is too large
Load Diff
228
CodingStyle.md
Normal file
228
CodingStyle.md
Normal file
@@ -0,0 +1,228 @@
|
||||
Write code in a clear, self-documenting style but use comments where necessary.
|
||||
Use Test Driven Development. It encourages designing interfaces first, before implementation.
|
||||
Don't Repeat Yourself, <20>D.R.Y.<2E>. Put redundant code in a class so it can be re-used and unit tested.
|
||||
Expose as little of a class as possible. Prefer private over protected. Prefer protected over public. The smaller the interface footprint, the easier it is to write unit tests and comprehend the operation of the class. This is the Interface Segregation Principle.
|
||||
Use language constants (enum or static const) with descriptive names instead of hard-coded <20>magic numbers.<2E>
|
||||
Make classes depend on as few external classes or routines as possible. Ideally, no dependencies.
|
||||
Don't limit flexibility of parameters by forcing the caller to use specific types where general types would work.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
# Coding Standards
|
||||
|
||||
Coding standards used here are extreme strict and consistent. The style
|
||||
evolved gradually over the years, incorporating generally acknowledged
|
||||
best-practice C++ advice, experience, and personal preference.
|
||||
|
||||
## Don't Repeat Yourself!
|
||||
|
||||
The [Don't Repeat Yourself][1] principle summarises the essence of what it
|
||||
means to write good code, in all languages, at all levels.
|
||||
|
||||
## Formatting
|
||||
|
||||
The goal of source code formatting should always be to make things as easy to
|
||||
read as possible. White space is used to guide the eye so that details are not
|
||||
overlooked. Blank lines are used to separate code into "paragraphs."
|
||||
|
||||
* No tab characters please.
|
||||
* Tab stops are set to 4 spaces.
|
||||
* Braces are indented in the [Allman style][2].
|
||||
* Always place a space before and after all binary operators,
|
||||
especially assignments (`operator=`).
|
||||
* The `!` operator should always be followed by a space.
|
||||
* The `~` operator should be preceded by a space, but not followed by one.
|
||||
* The `++` and `--` operators should have no spaces between the operator and
|
||||
the operand.
|
||||
* A space never appears before a comma, and always appears after a comma.
|
||||
* Always place a space before an opening parenthesis. One exception is if
|
||||
the parentheses are empty.
|
||||
* Don't put spaces after a parenthesis. A typical member function call might
|
||||
look like this: `foobar (1, 2, 3);`
|
||||
* In general, leave a blank line before an `if` statement.
|
||||
* In general, leave a blank line after a closing brace `}`.
|
||||
* Do not place code or comments on the same line as any opening or
|
||||
closing brace.
|
||||
* Do not write `if` statements all-on-one-line. The exception to this is when
|
||||
you've got a sequence of similar `if` statements, and are aligning them all
|
||||
vertically to highlight their similarities.
|
||||
* In an `if-else` statement, if you surround one half of the statement with
|
||||
braces, you also need to put braces around the other half, to match.
|
||||
* When writing a pointer type, use this spacing: `SomeObject* myObject`.
|
||||
Technically, a more correct spacing would be `SomeObject *myObject`, but
|
||||
it makes more sense for the asterisk to be grouped with the type name,
|
||||
since being a pointer is part of the type, not the variable name. The only
|
||||
time that this can lead to any problems is when you're declaring multiple
|
||||
pointers of the same type in the same statement - which leads on to the next
|
||||
rule:
|
||||
* When declaring multiple pointers, never do so in a single statement, e.g.
|
||||
`SomeObject* p1, *p2;` - instead, always split them out onto separate lines
|
||||
and write the type name again, to make it quite clear what's going on, and
|
||||
avoid the danger of missing out any vital asterisks.
|
||||
* The previous point also applies to references, so always put the `&` next to
|
||||
the type rather than the variable, e.g. `void foo (Thing const& thing)`. And
|
||||
don't put a space on both sides of the `*` or `&` - always put a space after
|
||||
it, but never before it.
|
||||
* The word `const` should be placed to the right of the thing that it modifies,
|
||||
for consistency. For example `int const` refers to an int which is const.
|
||||
`int const*` is a pointer to an int which is const. `int *const` is a const
|
||||
pointer to an int.
|
||||
* Always place a space in between the template angle brackets and the type
|
||||
name. Template code is already hard enough to read!
|
||||
|
||||
## Naming conventions
|
||||
|
||||
* Member variables and method names are written with camel-case, and never
|
||||
begin with a capital letter.
|
||||
* Class names are also written in camel-case, but always begin with a capital
|
||||
letter.
|
||||
* For global variables... well, you shouldn't have any, so it doesn't matter.
|
||||
* Class data members begin with `m_`, static data members begin with `s_`.
|
||||
Global variables begin with `g_`. This is so the scope of the corresponding
|
||||
declaration can be easily determined.
|
||||
* Avoid underscores in your names, especially leading or trailing underscores.
|
||||
In particular, leading underscores should be avoided, as these are often used
|
||||
in standard library code, so to use them in your own code looks quite jarring.
|
||||
* If you really have to write a macro for some reason, then make it all caps,
|
||||
with underscores to separate the words. And obviously make sure that its name
|
||||
is unlikely to clash with symbols used in other libraries or 3rd party code.
|
||||
|
||||
## Types, const-correctness
|
||||
|
||||
* If a method can (and should!) be const, make it const!
|
||||
* If a method definitely doesn't throw an exception (be careful!), mark it as
|
||||
`noexcept`
|
||||
* When returning a temporary object, e.g. a String, the returned object should
|
||||
be non-const, so that if the class has a C++11 move operator, it can be used.
|
||||
* If a local variable can be const, then make it const!
|
||||
* Remember that pointers can be const as well as primitives; For example, if
|
||||
you have a `char*` whose contents are going to be altered, you may still be
|
||||
able to make the pointer itself const, e.g. `char* const foobar = getFoobar();`.
|
||||
* Do not declare all your local variables at the top of a function or method
|
||||
(i.e. in the old-fashioned C-style). Declare them at the last possible moment,
|
||||
and give them as small a scope as possible.
|
||||
* Object parameters should be passed as `const&` wherever possible. Only
|
||||
pass a parameter as a copy-by-value object if you really need to mutate
|
||||
a local copy inside the method, and if making a local copy inside the method
|
||||
would be difficult.
|
||||
* Use portable `for()` loop variable scoping (i.e. do not have multiple for
|
||||
loops in the same scope that each re-declare the same variable name, as
|
||||
this fails on older compilers)
|
||||
* When you're testing a pointer to see if it's null, never write
|
||||
`if (myPointer)`. Always avoid that implicit cast-to-bool by writing it more
|
||||
fully: `if (myPointer != nullptr)`. And likewise, never ever write
|
||||
`if (! myPointer)`, instead always write `if (myPointer == nullptr)`.
|
||||
It is more readable that way.
|
||||
* Avoid C-style casts except when converting between primitive numeric types.
|
||||
Some people would say "avoid C-style casts altogether", but `static_cast` is
|
||||
a bit unreadable when you just want to cast an `int` to a `float`. But
|
||||
whenever a pointer is involved, or a non-primitive object, always use
|
||||
`static_cast`. And when you're reinterpreting data, always use
|
||||
`reinterpret_cast`.
|
||||
* Until C++ gets a universal 64-bit primitive type (part of the C++11
|
||||
standard), it's best to stick to the `int64` and `uint64` typedefs.
|
||||
|
||||
## Object lifetime and ownership
|
||||
|
||||
* Absolutely do NOT use `delete`, `deleteAndZero`, etc. There are very very few
|
||||
situations where you can't use a `ScopedPointer` or some other automatic
|
||||
lifetime management class.
|
||||
* Do not use `new` unless there's no alternative. Whenever you type `new`, always
|
||||
treat it as a failure to find a better solution. If a local variable can be
|
||||
allocated on the stack rather than the heap, then always do so.
|
||||
* Do not ever use `new` or `malloc` to allocate a C++ array. Always use a
|
||||
`HeapBlock` instead.
|
||||
* And just to make it doubly clear: Never use `malloc` or `calloc`.
|
||||
* If a parent object needs to create and own some kind of child object, always
|
||||
use composition as your first choice. If that's not possible (e.g. if the
|
||||
child needs a pointer to the parent for its constructor), then use a
|
||||
`ScopedPointer`.
|
||||
* If possible, pass an object as a reference rather than a pointer. If possible,
|
||||
make it a `const` reference.
|
||||
* Obviously avoid static and global values. Sometimes there's no alternative,
|
||||
but if there is an alternative, then use it, no matter how much effort it
|
||||
involves.
|
||||
* If allocating a local POD structure (e.g. an operating-system structure in
|
||||
native code), and you need to initialise it with zeros, use the `= { 0 };`
|
||||
syntax as your first choice for doing this. If for some reason that's not
|
||||
appropriate, use the `zerostruct()` function, or in case that isn't suitable,
|
||||
use `zeromem()`. Don't use `memset()`.
|
||||
|
||||
## Classes
|
||||
|
||||
* Declare a class's public section first, and put its constructors and
|
||||
destructor first. Any protected items come next, and then private ones.
|
||||
* Use the most restrictive access-specifier possible for each member. Prefer
|
||||
`private` over `protected`, and `protected` over `public`. Don't expose
|
||||
things unnecessarily.
|
||||
* Preferred positioning for any inherited classes is to put them to the right
|
||||
of the class name, vertically aligned, e.g.:
|
||||
class Thing : public Foo,
|
||||
private Bar
|
||||
{
|
||||
}
|
||||
* Put a class's member variables (which should almost always be private, of course),
|
||||
after all the public and protected method declarations.
|
||||
* Any private methods can go towards the end of the class, after the member
|
||||
variables.
|
||||
* If your class does not have copy-by-value semantics, derive the class from
|
||||
`Uncopyable`.
|
||||
* If your class is likely to be leaked, then derive your class from
|
||||
`LeakChecked<>`.
|
||||
* Constructors that take a single parameter should be default be marked
|
||||
`explicit`. Obviously there are cases where you do want implicit conversion,
|
||||
but always think about it carefully before writing a non-explicit constructor.
|
||||
* Do not use `NULL`, `null`, or 0 for a null-pointer. And especially never use
|
||||
'0L', which is particulary burdensome. Use `nullptr` instead - this is the
|
||||
C++2011 standard, so get used to it. There's a fallback definition for `nullptr`
|
||||
in Beast, so it's always possible to use it even if your compiler isn't yet
|
||||
C++2011 compliant.
|
||||
* All the C++ 'guru' books and articles are full of excellent and detailed advice
|
||||
on when it's best to use inheritance vs composition. If you're not already
|
||||
familiar with the received wisdom in these matters, then do some reading!
|
||||
|
||||
## Miscellaneous
|
||||
|
||||
* Constrain the scope of identifiers to the smallest area that needs it. Consider
|
||||
using nested classes or classes inside functions, if doing so will expose less
|
||||
interface and implementation overall.
|
||||
* `goto` statements should not be used at all, even if the alternative is
|
||||
more verbose code. The only exception is when implementing an algorithm in
|
||||
a function as a state machine.
|
||||
* Don't use macros! OK, obviously there are many situations where they're the
|
||||
right tool for the job, but treat them as a last resort. Certainly don't ever
|
||||
use a macro just to hold a constant value or to perform any kind of function
|
||||
that could have been done as a real inline function. And it goes without saying
|
||||
that you should give them names which aren't going to clash with other code.
|
||||
And `#undef` them after you've used them, if possible.
|
||||
* When using the `++` or `--` operators, never use post-increment if
|
||||
pre-increment could be used instead. Although it doesn't matter for
|
||||
primitive types, it's good practice to pre-increment since this can be
|
||||
much more efficient for more complex objects. In particular, if you're
|
||||
writing a for loop, always use pre-increment,
|
||||
e.g. `for (int = 0; i < 10; ++i)`
|
||||
* Never put an "else" statement after a "return"! This is well-explained in the
|
||||
LLVM coding standards...and a couple of other very good pieces of advice from
|
||||
the LLVM standards are in there as well.
|
||||
* When getting a possibly-null pointer and using it only if it's non-null, limit
|
||||
the scope of the pointer as much as possible - e.g. Do NOT do this:
|
||||
|
||||
Foo* f = getFoo ();
|
||||
if (f != nullptr)
|
||||
f->doSomething ();
|
||||
// other code
|
||||
f->doSomething (); // oops! f may be null!
|
||||
|
||||
..instead, prefer to write it like this, which reduces the scope of the
|
||||
pointer, making it impossible to write code that accidentally uses a null
|
||||
pointer:
|
||||
|
||||
if (Foo* f = getFoo ())
|
||||
f->doSomethingElse ();
|
||||
|
||||
// f is out-of-scope here, so impossible to use it if it's null
|
||||
|
||||
(This also results in smaller, cleaner code)
|
||||
|
||||
[1]: http://en.wikipedia.org/wiki/Don%27t_repeat_yourself
|
||||
[2]: http://en.wikipedia.org/wiki/Indent_style#Allman_style
|
||||
302
Doxyfile
Normal file
302
Doxyfile
Normal file
@@ -0,0 +1,302 @@
|
||||
# Doxyfile 1.8.3.1
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Project related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
DOXYFILE_ENCODING = UTF-8
|
||||
PROJECT_NAME = "Beast"
|
||||
PROJECT_NUMBER =
|
||||
PROJECT_BRIEF =
|
||||
PROJECT_LOGO =
|
||||
OUTPUT_DIRECTORY = Docs
|
||||
CREATE_SUBDIRS = NO
|
||||
OUTPUT_LANGUAGE = English
|
||||
BRIEF_MEMBER_DESC = YES
|
||||
REPEAT_BRIEF = YES
|
||||
ABBREVIATE_BRIEF =
|
||||
ALWAYS_DETAILED_SEC = NO
|
||||
INLINE_INHERITED_MEMB = NO
|
||||
FULL_PATH_NAMES = YES
|
||||
STRIP_FROM_PATH =
|
||||
STRIP_FROM_INC_PATH =
|
||||
SHORT_NAMES = NO
|
||||
JAVADOC_AUTOBRIEF = NO
|
||||
QT_AUTOBRIEF = NO
|
||||
MULTILINE_CPP_IS_BRIEF = NO
|
||||
INHERIT_DOCS = YES
|
||||
SEPARATE_MEMBER_PAGES = NO
|
||||
TAB_SIZE = 4
|
||||
ALIASES =
|
||||
TCL_SUBST =
|
||||
OPTIMIZE_OUTPUT_FOR_C = NO
|
||||
OPTIMIZE_OUTPUT_JAVA = NO
|
||||
OPTIMIZE_FOR_FORTRAN = NO
|
||||
OPTIMIZE_OUTPUT_VHDL = NO
|
||||
EXTENSION_MAPPING =
|
||||
MARKDOWN_SUPPORT = YES
|
||||
AUTOLINK_SUPPORT = YES
|
||||
BUILTIN_STL_SUPPORT = NO
|
||||
CPP_CLI_SUPPORT = NO
|
||||
SIP_SUPPORT = NO
|
||||
IDL_PROPERTY_SUPPORT = YES
|
||||
DISTRIBUTE_GROUP_DOC = NO
|
||||
SUBGROUPING = YES
|
||||
INLINE_GROUPED_CLASSES = NO
|
||||
INLINE_SIMPLE_STRUCTS = NO
|
||||
TYPEDEF_HIDES_STRUCT = NO
|
||||
SYMBOL_CACHE_SIZE = 0
|
||||
LOOKUP_CACHE_SIZE = 0
|
||||
#---------------------------------------------------------------------------
|
||||
# Build related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
EXTRACT_ALL = NO
|
||||
EXTRACT_PRIVATE = NO
|
||||
EXTRACT_PACKAGE = NO
|
||||
EXTRACT_STATIC = NO
|
||||
EXTRACT_LOCAL_CLASSES = YES
|
||||
EXTRACT_LOCAL_METHODS = NO
|
||||
EXTRACT_ANON_NSPACES = NO
|
||||
HIDE_UNDOC_MEMBERS = NO
|
||||
HIDE_UNDOC_CLASSES = NO
|
||||
HIDE_FRIEND_COMPOUNDS = NO
|
||||
HIDE_IN_BODY_DOCS = NO
|
||||
INTERNAL_DOCS = NO
|
||||
CASE_SENSE_NAMES = NO
|
||||
HIDE_SCOPE_NAMES = NO
|
||||
SHOW_INCLUDE_FILES = YES
|
||||
FORCE_LOCAL_INCLUDES = NO
|
||||
INLINE_INFO = YES
|
||||
SORT_MEMBER_DOCS = YES
|
||||
SORT_BRIEF_DOCS = NO
|
||||
SORT_MEMBERS_CTORS_1ST = NO
|
||||
SORT_GROUP_NAMES = NO
|
||||
SORT_BY_SCOPE_NAME = NO
|
||||
STRICT_PROTO_MATCHING = NO
|
||||
GENERATE_TODOLIST = YES
|
||||
GENERATE_TESTLIST = YES
|
||||
GENERATE_BUGLIST = YES
|
||||
GENERATE_DEPRECATEDLIST= YES
|
||||
ENABLED_SECTIONS =
|
||||
MAX_INITIALIZER_LINES = 30
|
||||
SHOW_USED_FILES = YES
|
||||
SHOW_FILES = YES
|
||||
SHOW_NAMESPACES = YES
|
||||
FILE_VERSION_FILTER =
|
||||
LAYOUT_FILE =
|
||||
CITE_BIB_FILES =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to warning and progress messages
|
||||
#---------------------------------------------------------------------------
|
||||
QUIET = NO
|
||||
WARNINGS = YES
|
||||
WARN_IF_UNDOCUMENTED = YES
|
||||
WARN_IF_DOC_ERROR = YES
|
||||
WARN_NO_PARAMDOC = NO
|
||||
WARN_FORMAT = "$file:$line: $text"
|
||||
WARN_LOGFILE =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the input files
|
||||
#---------------------------------------------------------------------------
|
||||
INPUT = modules
|
||||
INPUT_ENCODING = UTF-8
|
||||
FILE_PATTERNS =
|
||||
RECURSIVE = YES
|
||||
EXCLUDE = modules/beast_core/beast_core.h \
|
||||
modules/beast_core/beast_core.cpp \
|
||||
modules/beast_basics/beast_basics.cpp \
|
||||
modules/beast_basics/native \
|
||||
modules/beast_basics/zip/zlib
|
||||
EXCLUDE_SYMLINKS = NO
|
||||
EXCLUDE_PATTERNS =
|
||||
EXCLUDE_SYMBOLS =
|
||||
EXAMPLE_PATH =
|
||||
EXAMPLE_PATTERNS =
|
||||
EXAMPLE_RECURSIVE = NO
|
||||
IMAGE_PATH =
|
||||
INPUT_FILTER =
|
||||
FILTER_PATTERNS =
|
||||
FILTER_SOURCE_FILES = NO
|
||||
FILTER_SOURCE_PATTERNS =
|
||||
USE_MDFILE_AS_MAINPAGE =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to source browsing
|
||||
#---------------------------------------------------------------------------
|
||||
SOURCE_BROWSER = NO
|
||||
INLINE_SOURCES = NO
|
||||
STRIP_CODE_COMMENTS = YES
|
||||
REFERENCED_BY_RELATION = NO
|
||||
REFERENCES_RELATION = NO
|
||||
REFERENCES_LINK_SOURCE = YES
|
||||
USE_HTAGS = NO
|
||||
VERBATIM_HEADERS = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the alphabetical class index
|
||||
#---------------------------------------------------------------------------
|
||||
ALPHABETICAL_INDEX = YES
|
||||
COLS_IN_ALPHA_INDEX = 5
|
||||
IGNORE_PREFIX =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the HTML output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_HTML = YES
|
||||
HTML_OUTPUT = .
|
||||
HTML_FILE_EXTENSION = .html
|
||||
HTML_HEADER =
|
||||
HTML_FOOTER =
|
||||
HTML_STYLESHEET =
|
||||
HTML_EXTRA_STYLESHEET =
|
||||
HTML_EXTRA_FILES =
|
||||
HTML_COLORSTYLE_HUE = 220
|
||||
HTML_COLORSTYLE_SAT = 100
|
||||
HTML_COLORSTYLE_GAMMA = 80
|
||||
HTML_TIMESTAMP = YES
|
||||
HTML_DYNAMIC_SECTIONS = NO
|
||||
HTML_INDEX_NUM_ENTRIES = 100
|
||||
GENERATE_DOCSET = NO
|
||||
DOCSET_FEEDNAME = "Doxygen generated docs"
|
||||
DOCSET_BUNDLE_ID = org.doxygen.Project
|
||||
DOCSET_PUBLISHER_ID = org.doxygen.Publisher
|
||||
DOCSET_PUBLISHER_NAME = Publisher
|
||||
GENERATE_HTMLHELP = NO
|
||||
CHM_FILE =
|
||||
HHC_LOCATION =
|
||||
GENERATE_CHI = NO
|
||||
CHM_INDEX_ENCODING =
|
||||
BINARY_TOC = NO
|
||||
TOC_EXPAND = NO
|
||||
GENERATE_QHP = NO
|
||||
QCH_FILE =
|
||||
QHP_NAMESPACE = org.doxygen.Project
|
||||
QHP_VIRTUAL_FOLDER = doc
|
||||
QHP_CUST_FILTER_NAME =
|
||||
QHP_CUST_FILTER_ATTRS =
|
||||
QHP_SECT_FILTER_ATTRS =
|
||||
QHG_LOCATION =
|
||||
GENERATE_ECLIPSEHELP = NO
|
||||
ECLIPSE_DOC_ID = org.doxygen.Project
|
||||
DISABLE_INDEX = NO
|
||||
GENERATE_TREEVIEW = NO
|
||||
ENUM_VALUES_PER_LINE = 4
|
||||
TREEVIEW_WIDTH = 250
|
||||
EXT_LINKS_IN_WINDOW = NO
|
||||
FORMULA_FONTSIZE = 10
|
||||
FORMULA_TRANSPARENT = YES
|
||||
USE_MATHJAX = NO
|
||||
MATHJAX_FORMAT = HTML-CSS
|
||||
MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
|
||||
MATHJAX_EXTENSIONS =
|
||||
SEARCHENGINE = YES
|
||||
SERVER_BASED_SEARCH = NO
|
||||
EXTERNAL_SEARCH = NO
|
||||
SEARCHENGINE_URL =
|
||||
SEARCHDATA_FILE = searchdata.xml
|
||||
EXTERNAL_SEARCH_ID =
|
||||
EXTRA_SEARCH_MAPPINGS =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the LaTeX output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_LATEX = NO
|
||||
LATEX_OUTPUT = latex
|
||||
LATEX_CMD_NAME = latex
|
||||
MAKEINDEX_CMD_NAME = makeindex
|
||||
COMPACT_LATEX = NO
|
||||
PAPER_TYPE = a4
|
||||
EXTRA_PACKAGES =
|
||||
LATEX_HEADER =
|
||||
LATEX_FOOTER =
|
||||
PDF_HYPERLINKS = YES
|
||||
USE_PDFLATEX = YES
|
||||
LATEX_BATCHMODE = NO
|
||||
LATEX_HIDE_INDICES = NO
|
||||
LATEX_SOURCE_CODE = NO
|
||||
LATEX_BIB_STYLE = plain
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the RTF output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_RTF = NO
|
||||
RTF_OUTPUT = rtf
|
||||
COMPACT_RTF = NO
|
||||
RTF_HYPERLINKS = NO
|
||||
RTF_STYLESHEET_FILE =
|
||||
RTF_EXTENSIONS_FILE =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the man page output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_MAN = NO
|
||||
MAN_OUTPUT = man
|
||||
MAN_EXTENSION = .3
|
||||
MAN_LINKS = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the XML output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_XML = NO
|
||||
XML_OUTPUT = xml
|
||||
XML_SCHEMA =
|
||||
XML_DTD =
|
||||
XML_PROGRAMLISTING = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options for the AutoGen Definitions output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_AUTOGEN_DEF = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the Perl module output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_PERLMOD = NO
|
||||
PERLMOD_LATEX = NO
|
||||
PERLMOD_PRETTY = YES
|
||||
PERLMOD_MAKEVAR_PREFIX =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the preprocessor
|
||||
#---------------------------------------------------------------------------
|
||||
ENABLE_PREPROCESSING = YES
|
||||
MACRO_EXPANSION = NO
|
||||
EXPAND_ONLY_PREDEF = NO
|
||||
SEARCH_INCLUDES = YES
|
||||
INCLUDE_PATH =
|
||||
INCLUDE_FILE_PATTERNS =
|
||||
PREDEFINED =
|
||||
EXPAND_AS_DEFINED =
|
||||
SKIP_FUNCTION_MACROS = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration::additions related to external references
|
||||
#---------------------------------------------------------------------------
|
||||
TAGFILES =
|
||||
GENERATE_TAGFILE =
|
||||
ALLEXTERNALS = NO
|
||||
EXTERNAL_GROUPS = YES
|
||||
PERL_PATH = /usr/bin/perl
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the dot tool
|
||||
#---------------------------------------------------------------------------
|
||||
CLASS_DIAGRAMS = YES
|
||||
MSCGEN_PATH =
|
||||
HIDE_UNDOC_RELATIONS = YES
|
||||
HAVE_DOT = YES
|
||||
DOT_NUM_THREADS = 0
|
||||
DOT_FONTNAME = Helvetica
|
||||
DOT_FONTSIZE = 10
|
||||
DOT_FONTPATH =
|
||||
CLASS_GRAPH = YES
|
||||
COLLABORATION_GRAPH = YES
|
||||
GROUP_GRAPHS = YES
|
||||
UML_LOOK = NO
|
||||
UML_LIMIT_NUM_FIELDS = 10
|
||||
TEMPLATE_RELATIONS = NO
|
||||
INCLUDE_GRAPH = YES
|
||||
INCLUDED_BY_GRAPH = YES
|
||||
CALL_GRAPH = NO
|
||||
CALLER_GRAPH = NO
|
||||
GRAPHICAL_HIERARCHY = YES
|
||||
DIRECTORY_GRAPH = YES
|
||||
DOT_IMAGE_FORMAT = png
|
||||
INTERACTIVE_SVG = NO
|
||||
DOT_PATH =
|
||||
DOTFILE_DIRS =
|
||||
MSCFILE_DIRS =
|
||||
DOT_GRAPH_MAX_NODES = 50
|
||||
MAX_DOT_GRAPH_DEPTH = 0
|
||||
DOT_TRANSPARENT = NO
|
||||
DOT_MULTI_TARGETS = NO
|
||||
GENERATE_LEGEND = YES
|
||||
DOT_CLEANUP = YES
|
||||
|
||||
31
ReadMe.md
Normal file
31
ReadMe.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# Beast: An amazing cross platform library
|
||||
|
||||
Contains cross platform objects to do a variety of useful things.
|
||||
No external dependencies, no complicated build steps.
|
||||
|
||||
Things people need for building peer to peer, concurrent, cryptographic systems.
|
||||
|
||||
The hope is that this will replace the use of boost and other cumbersome jalopies.
|
||||
|
||||
## JUCE
|
||||
|
||||
Parts of Beast are based on the juce_core module which is provided under the ISC
|
||||
license. More information about JUCE is available at
|
||||
|
||||
http://www.juce.com
|
||||
|
||||
## License
|
||||
|
||||
Beast is provided under the terms of the ISC license:
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
87
TODO.txt
Normal file
87
TODO.txt
Normal file
@@ -0,0 +1,87 @@
|
||||
--------------------------------------------------------------------------------
|
||||
BEAST TODO
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
- Use new file naming convention
|
||||
|
||||
- Rename ReadWriteMutex to SharedMutex
|
||||
|
||||
- Use SemanticVersion for beast version numbers to replace BEAST_VERSION
|
||||
|
||||
- add support for a __PRETTY_FUNCTION__ equivalent for all environments
|
||||
|
||||
- add expectThrow() to UnitTest, where it expects an exception
|
||||
|
||||
- Import secp256k1 from sipa
|
||||
|
||||
- HashMap work:
|
||||
- Add unit test
|
||||
- Return size_t from hash function, take out upperLimit, move mod % to caller
|
||||
- Make hash function a functor using operator()
|
||||
- Implement HardenedHashFunctions
|
||||
- Fix problem with assigning to the result of operator[] maybe use a proxy?
|
||||
|
||||
- Set sqlite thread safety model to '2' in beast_sqlite
|
||||
|
||||
- Document and rename all the sqdb files and classes
|
||||
|
||||
- Specialize UnsignedInteger<> for peformance in the storage format
|
||||
|
||||
- Rename HeapBlock routines to not conflict with _CRTDBG_MAP_ALLOC macros
|
||||
|
||||
- Design a WeakPtr / SharedPtr / SharedObject intrusive system
|
||||
|
||||
- Implement beast::Bimap?
|
||||
|
||||
- Use Bimap for storage in the DeadlineTimer::Manager, to support
|
||||
thousands of timers.
|
||||
|
||||
- Think about adding a shouldStop bool to InterruptibleThread, along
|
||||
with a shouldStop () function returning bool, and a stop() method.
|
||||
|
||||
- Make OwnedArray add routines return a pointer instead of reference
|
||||
|
||||
- Tidy up CacheLine, MemoryAlignment
|
||||
|
||||
- Remove anything having to do with DLL builds like
|
||||
BEAST_DLL, BEAST_DLL_BUILD, BEAST_DISABLE_DLL_ALLOCATORS
|
||||
|
||||
- Fix FifoFreeStoreWithTLS reference counting bug
|
||||
|
||||
- Implement a reasonable substitute for boost's thread_local_storage
|
||||
|
||||
- Think about doing away with BEAST_CALLTYPE and BEAST_API
|
||||
|
||||
- Decide if headers should just include BeastConfig.h instead of making the
|
||||
host program do it.
|
||||
|
||||
- Rename malloc/calloc JUCE members that conflict with the debug CRT from MSVC
|
||||
|
||||
- Make beast::HashMap support assignment via operator[]
|
||||
|
||||
- Reformat every Doxygen comment
|
||||
- Fix Doxygen metatags
|
||||
- update Beast Doxyfile
|
||||
|
||||
- Rename include guards to boost style, e.g. BEAST_THROW_H_INCLUDED
|
||||
|
||||
- Decide if we should get rid of AtomicCounter, AtomicFlag, AtomicPointer, AtomicState
|
||||
|
||||
- Clean up CacheLine, StaticObject
|
||||
|
||||
- Clean up ConcurrentObject
|
||||
|
||||
- Rename SharedData to SharedState or something?
|
||||
|
||||
- Figure out what to do with ReadWriteLock, and NamedPipe which uses it?
|
||||
|
||||
- Put BEAST_PUBLIC_FUNCTION in front of all loose functions
|
||||
|
||||
- restructure the repo sources to look like this:
|
||||
/Source/beast/beast_core/beast_core.h
|
||||
etc...
|
||||
- Put the BeastConfig.h at the root of the repo.
|
||||
- Make sure the template BeastConfig.h is included in the Doxyfile
|
||||
|
||||
- Implement robust key/value database with bulk write
|
||||
|
||||
445
beast/intrusive/ForwardList.h
Normal file
445
beast/intrusive/ForwardList.h
Normal file
@@ -0,0 +1,445 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_INTRUSIVE_FORWARDLIST_H_INCLUDED
|
||||
#define BEAST_INTRUSIVE_FORWARDLIST_H_INCLUDED
|
||||
|
||||
#include <iterator>
|
||||
|
||||
#include "PointerTraits.h"
|
||||
#include "../mpl.h"
|
||||
|
||||
// Ideas based on boost
|
||||
|
||||
namespace beast {
|
||||
namespace intrusive {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace detail {
|
||||
|
||||
// Holds the size field
|
||||
struct SizeHolder
|
||||
{
|
||||
public:
|
||||
typedef std::size_t size_type;
|
||||
|
||||
inline size_type size () const noexcept
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
inline void set (size_type new_size) noexcept
|
||||
{
|
||||
m_size = new_size;
|
||||
}
|
||||
|
||||
inline void increment () noexcept
|
||||
{
|
||||
++m_size;
|
||||
}
|
||||
|
||||
inline void decrement () noexcept
|
||||
{
|
||||
--m_size;
|
||||
}
|
||||
|
||||
private:
|
||||
size_type m_size;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <class VoidPointer>
|
||||
struct ForwardListNode
|
||||
{
|
||||
typedef typename PointerTraits <VoidPointer>::template rebind_pointer <ForwardListNode>::type node_ptr;
|
||||
|
||||
node_ptr next;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Provides value_traits for when T derives from Node
|
||||
template <class T, class NodeTraits>
|
||||
struct DerivedValueTraits
|
||||
{
|
||||
typedef NodeTraits node_traits;
|
||||
typedef T value_type;
|
||||
typedef typename node_traits::node node;
|
||||
typedef typename node_traits::node_ptr node_ptr;
|
||||
typedef typename node_traits::const_node_ptr const_node_ptr;
|
||||
typedef typename mpl::PointerToOther <node_ptr, T>::type pointer;
|
||||
typedef typename mpl::PointerToOther <node_ptr, const T>::type const_pointer;
|
||||
typedef typename PointerTraits <pointer>::reference reference;
|
||||
typedef typename PointerTraits <const_pointer>::reference const_reference;
|
||||
|
||||
static node_ptr to_node_ptr (reference value)
|
||||
{
|
||||
return node_ptr (&value);
|
||||
}
|
||||
|
||||
static const_node_ptr to_node_ptr (const_reference value)
|
||||
{
|
||||
return node_ptr (&value);
|
||||
}
|
||||
|
||||
static pointer to_value_ptr (node_ptr const& n)
|
||||
{
|
||||
return pointer (&static_cast <value_type&> (*n));
|
||||
}
|
||||
|
||||
static const_pointer to_value_ptr (const_node_ptr const &n)
|
||||
{
|
||||
return const_pointer (&static_cast <value_type const&> (*n));
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <class VoidPointer, typename Tag>
|
||||
struct ForwardListNodeTraits
|
||||
{
|
||||
typedef ForwardListNode <VoidPointer> node;
|
||||
|
||||
typedef typename PointerTraits <VoidPointer>::
|
||||
template rebind_pointer <node> node_ptr;
|
||||
|
||||
typedef typename PointerTraits <VoidPointer>::
|
||||
template rebind_pointer <node const> const_node_ptr;
|
||||
|
||||
static node_ptr get_next (const_node_ptr const& n)
|
||||
{
|
||||
return n->m_next;
|
||||
}
|
||||
|
||||
static node_ptr get_next (node_ptr const& n)
|
||||
{
|
||||
return n->m_next;
|
||||
}
|
||||
|
||||
static void set_next (node_ptr const& n, node_ptr const& next)
|
||||
{
|
||||
n->m_next = next;
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <class Container, bool IsConst>
|
||||
class ForwardListIterator
|
||||
: public std::iterator <
|
||||
std::forward_iterator_tag,
|
||||
typename Container::value_type,
|
||||
typename Container::difference_type,
|
||||
typename mpl::IfCond <IsConst,
|
||||
typename Container::const_pointer,
|
||||
typename Container::pointer>::type,
|
||||
typename mpl::IfCond <IsConst,
|
||||
typename Container::const_reference,
|
||||
typename Container::reference>::type>
|
||||
{
|
||||
protected:
|
||||
typedef typename Container::value_traits value_traits;
|
||||
typedef typename Container::node_traits node_traits;
|
||||
typedef typename node_traits::node node;
|
||||
typedef typename node_traits::node_ptr node_ptr;
|
||||
typedef typename PointerTraits <node_ptr>::
|
||||
template rebind_pointer <void>::type void_pointer;
|
||||
|
||||
public:
|
||||
typedef typename Container::value_type value_type;
|
||||
typedef typename mpl::IfCond <IsConst,
|
||||
typename Container::const_pointer,
|
||||
typename Container::pointer>::type pointer;
|
||||
typedef typename mpl::IfCond <IsConst,
|
||||
typename Container::const_reference,
|
||||
typename Container::reference>::type reference;
|
||||
|
||||
ForwardListIterator ()
|
||||
: m_node ()
|
||||
{
|
||||
}
|
||||
|
||||
explicit ForwardListIterator (ForwardListIterator <Container, false> const& other)
|
||||
: m_node (other.pointed_node ())
|
||||
{
|
||||
}
|
||||
|
||||
node_ptr const& pointed_node () const noexcept
|
||||
{
|
||||
return m_node;
|
||||
}
|
||||
|
||||
ForwardListIterator& operator= (node_ptr const& node)
|
||||
{
|
||||
m_node = node;
|
||||
return static_cast <ForwardListIterator&> (*this);
|
||||
}
|
||||
|
||||
ForwardListIterator& operator++ ()
|
||||
{
|
||||
m_node = node_traits::get_next (m_node);
|
||||
return static_cast <ForwardListIterator&> (*this);
|
||||
}
|
||||
|
||||
ForwardListIterator operator++ (int)
|
||||
{
|
||||
ForwardListIterator result (*this);
|
||||
m_node = node_traits::get_next (m_node);
|
||||
return result;
|
||||
}
|
||||
|
||||
friend bool operator== (ForwardListIterator const& lhs,
|
||||
ForwardListIterator const& rhs)
|
||||
{
|
||||
return lhs.m_node == rhs.m_node;
|
||||
}
|
||||
|
||||
friend bool operator!= (ForwardListIterator const& lhs,
|
||||
ForwardListIterator const& rhs)
|
||||
{
|
||||
return ! (lhs == rhs);
|
||||
}
|
||||
|
||||
reference operator* () const
|
||||
{
|
||||
return *this->operator-> ();
|
||||
}
|
||||
|
||||
pointer operator-> () const
|
||||
{
|
||||
return value_traits::to_value_ptr (m_node);
|
||||
}
|
||||
|
||||
private:
|
||||
node_ptr m_node;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <class NodeTraits>
|
||||
class ForwardListAlgorithms
|
||||
{
|
||||
public:
|
||||
typedef typename NodeTraits::node node;
|
||||
typedef typename NodeTraits::node_ptr node_ptr;
|
||||
typedef typename NodeTraits::const_node_ptr const_node_ptr;
|
||||
typedef NodeTraits node_traits;
|
||||
|
||||
static void init (node_ptr const& n)
|
||||
{
|
||||
NodeTraits::set_next (n, node_ptr());
|
||||
}
|
||||
|
||||
static bool unique (const_node_ptr const& this_node)
|
||||
{
|
||||
node_ptr next = NodeTraits::get_next (this_node);
|
||||
return !next || next == this_node;
|
||||
}
|
||||
|
||||
static void link_after (node_ptr const& prev_node, node_ptr const& this_node)
|
||||
{
|
||||
NodeTraits::set_next (this_node, NodeTraits::get_next (prev_node));
|
||||
NodeTraits::set_next (prev_node, this_node);
|
||||
}
|
||||
|
||||
static void unlink_after (node_ptr const& prev_node)
|
||||
{
|
||||
const_node_ptr this_node (NodeTraits::get_next (prev_node));
|
||||
NodeTraits::set_next (prev_node, NodeTraits::get_next (this_node));
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Singly-linked intrusive list. */
|
||||
template <typename T, typename Tag = void>
|
||||
class ForwardList
|
||||
{
|
||||
public:
|
||||
typedef DerivedValueTraits <T, ForwardListNodeTraits <T, Tag> >
|
||||
value_traits;
|
||||
typedef typename value_traits::pointer pointer;
|
||||
typedef typename value_traits::const_pointer const_pointer;
|
||||
typedef typename PointerTraits <pointer>::element_type value_type;
|
||||
typedef typename PointerTraits <pointer>::reference reference;
|
||||
typedef typename PointerTraits <pointer>::const_reference const_reference;
|
||||
typedef typename PointerTraits <pointer>::difference_type difference_type;
|
||||
typedef std::size_t size_type;
|
||||
typedef ForwardListIterator <ForwardList, false> iterator;
|
||||
typedef ForwardListIterator <ForwardList, true> const_iterator;
|
||||
typedef typename value_traits::node_traits node_traits;
|
||||
typedef typename node_traits::node node;
|
||||
typedef typename node_traits::node_ptr node_ptr;
|
||||
typedef typename node_traits::const_node_ptr const_node_ptr;
|
||||
typedef ForwardListAlgorithms <node_traits> node_algorithms;
|
||||
|
||||
typedef node Node;
|
||||
|
||||
private:
|
||||
typedef detail::SizeHolder size_traits;
|
||||
|
||||
void default_construct ()
|
||||
{
|
||||
get_size_traits ().set (size_type (0));
|
||||
node_algorithms::init (this->get_root_node ());
|
||||
}
|
||||
|
||||
node_ptr get_end_node ()
|
||||
{
|
||||
return node_ptr ();
|
||||
}
|
||||
|
||||
const_node_ptr get_end_node () const
|
||||
{
|
||||
return const_node_ptr ();
|
||||
}
|
||||
|
||||
node_ptr get_root_node ()
|
||||
{
|
||||
return PointerTraits <node_ptr>::pointer_to (m_root);
|
||||
}
|
||||
|
||||
const_node_ptr get_root_node () const
|
||||
{
|
||||
return PointerTraits <const_node_ptr>::pointer_to (m_root);
|
||||
}
|
||||
|
||||
size_traits& get_size_traits () noexcept
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
size_traits const& get_size_traits () const noexcept
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
static node_ptr uncast (const_node_ptr const& ptr)
|
||||
{
|
||||
return PointerTraits <node_ptr>::const_cast_from (ptr);
|
||||
}
|
||||
|
||||
public:
|
||||
ForwardList ()
|
||||
{
|
||||
default_construct ();
|
||||
}
|
||||
|
||||
void clear ()
|
||||
{
|
||||
default_construct ();
|
||||
}
|
||||
|
||||
void push_front (reference value)
|
||||
{
|
||||
node_ptr this_node (value_traits::to_node_ptr (value));
|
||||
node_algorithms::link_after (this->get_root_node (), this_node);
|
||||
this->get_size_traits ().increment ();
|
||||
}
|
||||
|
||||
void pop_front ()
|
||||
{
|
||||
//node_ptr this_node (node_traits::get_next (this->get_root ()));
|
||||
node_algorithms::unlink_after (this->get_root_node ());
|
||||
this->get_size_traits ().decrement ();
|
||||
}
|
||||
|
||||
reference front ()
|
||||
{
|
||||
return *value_traits::to_value_ptr (node_traits::get_next (this->get_root_node ()));
|
||||
}
|
||||
|
||||
const_reference front () const
|
||||
{
|
||||
return *value_traits::to_value_ptr (uncat (node_traits::get_next (this->get_root_node ())));
|
||||
}
|
||||
|
||||
iterator begin ()
|
||||
{
|
||||
return iterator (node_traits::get_next (this->get_root_node (), this));
|
||||
}
|
||||
|
||||
const_iterator begin () const
|
||||
{
|
||||
return const_iterator (node_traits::get_next (this->get_root_node (), this));
|
||||
}
|
||||
|
||||
const_iterator cbegin () const
|
||||
{
|
||||
return this->begin ();
|
||||
}
|
||||
|
||||
iterator end ()
|
||||
{
|
||||
return iterator (this->get_end_node (), this);
|
||||
}
|
||||
|
||||
const_iterator end () const
|
||||
{
|
||||
return const_iterator (this->get_end_node (), this);
|
||||
}
|
||||
|
||||
const_iterator cend () const
|
||||
{
|
||||
return this->end ();
|
||||
}
|
||||
|
||||
iterator before_begin ()
|
||||
{
|
||||
return iterator (this->get_root_node (), this);
|
||||
}
|
||||
|
||||
const_iterator before_begin () const
|
||||
{
|
||||
return const_iterator (this->get_root_node (), this);
|
||||
}
|
||||
|
||||
const_iterator cbefore_begin () const
|
||||
{
|
||||
return before_begin ();
|
||||
}
|
||||
|
||||
bool empty () const
|
||||
{
|
||||
return node_algorithms::unique (this->get_root_node ());
|
||||
}
|
||||
|
||||
iterator iterator_to (reference value)
|
||||
{
|
||||
return iterator (value_traits::to_node_ptr (value), this);
|
||||
}
|
||||
|
||||
const_iterator iterator_to (const_reference value) const
|
||||
{
|
||||
return const_iterator (value_traits::to_node_ptr (const_cast <reference> (value)), this);
|
||||
}
|
||||
|
||||
private:
|
||||
node m_root;
|
||||
size_traits m_size;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
87
beast/intrusive/PointerTraits.h
Normal file
87
beast/intrusive/PointerTraits.h
Normal file
@@ -0,0 +1,87 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_INTRUSIVE_POINTERTRAITS_H_INCLUDED
|
||||
#define BEAST_INTRUSIVE_POINTERTRAITS_H_INCLUDED
|
||||
|
||||
namespace beast {
|
||||
namespace intrusive {
|
||||
|
||||
// an unspecialized PointerTraits is ill-defined
|
||||
template <typename P>
|
||||
struct PointerTraits;
|
||||
|
||||
// specializations to remove cv-qualifiers
|
||||
template <typename P>
|
||||
struct PointerTraits <P const> : PointerTraits <P> { };
|
||||
template <typename P>
|
||||
struct PointerTraits <P volatile> : PointerTraits <P> { };
|
||||
template <typename P>
|
||||
struct PointerTraits <P const volatile> : PointerTraits <P> { };
|
||||
// specialization to remove a reference attribute
|
||||
template <typename P>
|
||||
struct PointerTraits <P&> : PointerTraits <P> { };
|
||||
|
||||
// specialization for raw pointers
|
||||
template <typename T>
|
||||
struct PointerTraits <T*>
|
||||
{
|
||||
typedef T element_type;
|
||||
typedef T* pointer;
|
||||
typedef T& reference;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
|
||||
template <class U>
|
||||
struct rebind_pointer
|
||||
{
|
||||
typedef U* type;
|
||||
};
|
||||
|
||||
static pointer pointer_to (reference r)
|
||||
{
|
||||
return static_cast <pointer> (
|
||||
static_cast <void*> (
|
||||
const_cast <char*> (
|
||||
&reinterpret_cast <const char&> (
|
||||
r))));
|
||||
}
|
||||
|
||||
template <class U>
|
||||
static pointer static_cast_from (U* u)
|
||||
{
|
||||
return static_cast <pointer> (u);
|
||||
}
|
||||
|
||||
template <class U>
|
||||
static pointer const_cast_from (U* u)
|
||||
{
|
||||
return const_cast <pointer> (u);
|
||||
}
|
||||
|
||||
template <class U>
|
||||
static pointer dynamic_cast_from (U* u)
|
||||
{
|
||||
return dynamic_cast <pointer> (u);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
31
beast/mpl.h
Normal file
31
beast/mpl.h
Normal file
@@ -0,0 +1,31 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_MPL_H_INCLUDED
|
||||
#define BEAST_MPL_H_INCLUDED
|
||||
|
||||
#include "mpl/AddConst.h"
|
||||
#include "mpl/IfCond.h"
|
||||
#include "mpl/PointerToOther.h"
|
||||
#include "mpl/RemoveConst.h"
|
||||
#include "mpl/RemoveConstVolatile.h"
|
||||
#include "mpl/RemoveReference.h"
|
||||
#include "mpl/RemoveVolatile.h"
|
||||
|
||||
#endif
|
||||
38
beast/mpl/AddConst.h
Normal file
38
beast/mpl/AddConst.h
Normal file
@@ -0,0 +1,38 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_MPL_ADDCONST_H_INCLUDED
|
||||
#define BEAST_MPL_ADDCONST_H_INCLUDED
|
||||
|
||||
// Ideas based on boost
|
||||
|
||||
namespace beast {
|
||||
namespace mpl {
|
||||
|
||||
/// Add the `const` qualifier to a type.
|
||||
template <typename T>
|
||||
struct AddConst
|
||||
{
|
||||
typedef T const type;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
46
beast/mpl/IfCond.h
Normal file
46
beast/mpl/IfCond.h
Normal file
@@ -0,0 +1,46 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_MPL_IFCOND_H_INCLUDED
|
||||
#define BEAST_MPL_IFCOND_H_INCLUDED
|
||||
|
||||
namespace beast {
|
||||
namespace mpl {
|
||||
|
||||
// Ideas based on boost
|
||||
|
||||
/// Select between T1 or T2 depending on Condition.
|
||||
/// @{
|
||||
template <bool Condition, typename T1, typename T2>
|
||||
struct IfCond
|
||||
{
|
||||
typedef T1 type;
|
||||
};
|
||||
|
||||
template <typename T1, typename T2>
|
||||
struct IfCond <false, T1, T2>
|
||||
{
|
||||
typedef T2 type;
|
||||
};
|
||||
/// @}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
68
beast/mpl/PointerToOther.h
Normal file
68
beast/mpl/PointerToOther.h
Normal file
@@ -0,0 +1,68 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_MPL_POINTERTOOTHERH_INCLUDED
|
||||
#define BEAST_MPL_POINTERTOOTHERH_INCLUDED
|
||||
|
||||
namespace beast {
|
||||
namespace mpl {
|
||||
|
||||
// Ideas based on boost
|
||||
|
||||
/** Declares a type which is a pointer or smart pointer to U, depending on T.
|
||||
This works for smart pointer containers with up to three template
|
||||
parameters. More specializations can be added for containers with
|
||||
more than three template parameters.
|
||||
*/
|
||||
/// @{
|
||||
template <class T, class U>
|
||||
struct PointerToOther;
|
||||
|
||||
template <class T, class U,
|
||||
template <class> class SmartPointer>
|
||||
struct PointerToOther <SmartPointer <T>, U>
|
||||
{
|
||||
typedef SmartPointer <U> type;
|
||||
};
|
||||
|
||||
template <class T, class T2, class U,
|
||||
template <class, class> class SmartPointer>
|
||||
struct PointerToOther <SmartPointer <T, T2>, U>
|
||||
{
|
||||
typedef SmartPointer <U, T2> type;
|
||||
};
|
||||
|
||||
template <class T, class T2, class T3, class U,
|
||||
template<class, class, class> class SmartPointer>
|
||||
struct PointerToOther <SmartPointer <T, T2, T3>, U>
|
||||
{
|
||||
typedef SmartPointer <U, T2, T3> type;
|
||||
};
|
||||
|
||||
template <class T, class U>
|
||||
struct PointerToOther <T*, U>
|
||||
{
|
||||
typedef U* type;
|
||||
};
|
||||
/// @}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
46
beast/mpl/RemoveConst.h
Normal file
46
beast/mpl/RemoveConst.h
Normal file
@@ -0,0 +1,46 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_MPL_REMOVECONST_H_INCLUDED
|
||||
#define BEAST_MPL_REMOVECONST_H_INCLUDED
|
||||
|
||||
// Ideas based on boost
|
||||
|
||||
namespace beast {
|
||||
namespace mpl {
|
||||
|
||||
/// Remove the `const` qualifier from a type.
|
||||
/// @{
|
||||
template <typename T>
|
||||
struct RemoveConst
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct RemoveConst <T const>
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
/// @}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
43
beast/mpl/RemoveConstVolatile.h
Normal file
43
beast/mpl/RemoveConstVolatile.h
Normal file
@@ -0,0 +1,43 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_MPL_REMOVECONSTVOLATILE_H_INCLUDED
|
||||
#define BEAST_MPL_REMOVECONSTVOLATILE_H_INCLUDED
|
||||
|
||||
#include "RemoveConst.h"
|
||||
#include "RemoveVolatile.h"
|
||||
|
||||
// Ideas based on boost
|
||||
|
||||
namespace beast {
|
||||
namespace mpl {
|
||||
|
||||
/// Remove both the `const` and `volatile` qualifiers from a type.
|
||||
template <typename T>
|
||||
struct RemoveConstVolatile
|
||||
{
|
||||
typedef typename RemoveConst <
|
||||
typename RemoveVolatile <T>::type
|
||||
>::type type;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
46
beast/mpl/RemoveReference.h
Normal file
46
beast/mpl/RemoveReference.h
Normal file
@@ -0,0 +1,46 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_MPL_REMOVEREFERENCE_H_INCLUDED
|
||||
#define BEAST_MPL_REMOVEREFERENCE_H_INCLUDED
|
||||
|
||||
namespace beast {
|
||||
namespace mpl {
|
||||
|
||||
// Ideas based on boost
|
||||
|
||||
/// Remove the reference qualifier from a type.
|
||||
/// @{
|
||||
template <class T>
|
||||
struct RemoveReference
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct RemoveReference <T&>
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
/// @}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
46
beast/mpl/RemoveVolatile.h
Normal file
46
beast/mpl/RemoveVolatile.h
Normal file
@@ -0,0 +1,46 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_MPL_REMOVEVOLATILE_H_INCLUDED
|
||||
#define BEAST_MPL_REMOVEVOLATILE_H_INCLUDED
|
||||
|
||||
// Ideas based on boost
|
||||
|
||||
namespace beast {
|
||||
namespace mpl {
|
||||
|
||||
/// Remove the `volatile` qualifier from a type.
|
||||
/// @{
|
||||
template <typename T>
|
||||
struct RemoveVolatile
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct RemoveVolatile <T volatile>
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
/// @}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
100
modules/beast_asio/async/ComposedAsyncOperation.h
Normal file
100
modules/beast_asio/async/ComposedAsyncOperation.h
Normal file
@@ -0,0 +1,100 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_ASYNC_COMPOSEDASYNCOPERATION_H_INCLUDED
|
||||
#define BEAST_ASIO_ASYNC_COMPOSEDASYNCOPERATION_H_INCLUDED
|
||||
|
||||
/** Base class for creating composed asynchronous operations.
|
||||
The composed operation will have its operator() overloads called with
|
||||
the same context and execution safety guarantees as the original
|
||||
SharedHandler.
|
||||
*/
|
||||
class ComposedAsyncOperation : public SharedHandler
|
||||
{
|
||||
protected:
|
||||
/** Construct the composed operation.
|
||||
The composed operation will execute in the context of the
|
||||
SharedHandler. A reference to the SharedHandler is maintained
|
||||
for the lifetime of the composed operation.
|
||||
*/
|
||||
ComposedAsyncOperation (std::size_t size, SharedHandlerPtr const& ptr)
|
||||
: m_size (size)
|
||||
, m_ptr (ptr)
|
||||
{
|
||||
// Illegal to do anything with handler here, because
|
||||
// usually it hasn't been assigned by the derived class yet.
|
||||
}
|
||||
|
||||
~ComposedAsyncOperation ()
|
||||
{
|
||||
}
|
||||
|
||||
void invoke (invoked_type& invoked)
|
||||
{
|
||||
boost_asio_handler_invoke_helpers::
|
||||
invoke (invoked, *m_ptr);
|
||||
}
|
||||
|
||||
void* allocate (std::size_t size)
|
||||
{
|
||||
return boost_asio_handler_alloc_helpers::
|
||||
allocate (size, *m_ptr);
|
||||
}
|
||||
|
||||
void deallocate (void* p, std::size_t size)
|
||||
{
|
||||
boost_asio_handler_alloc_helpers::
|
||||
deallocate (p, size, *m_ptr);
|
||||
}
|
||||
|
||||
/** Override this function as needed.
|
||||
Usually you will logical-and your own continuation condition. In
|
||||
the following example, isContinuing is a derived class member:
|
||||
|
||||
@code
|
||||
|
||||
bool derived::is_continuation ()
|
||||
{
|
||||
bool const ourResult = this->isContinuing ()
|
||||
return ourResult || ComposedAsyncOperation <Handler>::is_contiation ();
|
||||
}
|
||||
|
||||
@endcode
|
||||
*/
|
||||
bool is_continuation ()
|
||||
{
|
||||
#if BEAST_ASIO_HAS_CONTINUATION_HOOKS
|
||||
return boost_asio_handler_cont_helpers::
|
||||
is_continuation (*m_ptr);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void destroy ()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
private:
|
||||
std::size_t const m_size;
|
||||
SharedHandlerPtr const m_ptr;
|
||||
};
|
||||
|
||||
#endif
|
||||
47
modules/beast_asio/async/SharedHandler.cpp
Normal file
47
modules/beast_asio/async/SharedHandler.cpp
Normal file
@@ -0,0 +1,47 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
void SharedHandler::operator() ()
|
||||
{
|
||||
pure_virtual_called (__FILE__, __LINE__);
|
||||
}
|
||||
|
||||
void SharedHandler::operator() (error_code const&)
|
||||
{
|
||||
pure_virtual_called (__FILE__, __LINE__);
|
||||
}
|
||||
|
||||
void SharedHandler::operator() (error_code const&, std::size_t)
|
||||
{
|
||||
pure_virtual_called (__FILE__, __LINE__);
|
||||
}
|
||||
|
||||
void SharedHandler::pure_virtual_called (char const* fileName, int lineNumber)
|
||||
{
|
||||
// These shouldn't be getting called. But since the object returned
|
||||
// by most implementations of bind have operator() up to high arity
|
||||
// levels, it is not generally possible to write a traits test that
|
||||
// works in all scenarios for detecting a particular signature of a
|
||||
// handler.
|
||||
//
|
||||
// We use Throw here so beast has a chance to dump the stack BEFORE
|
||||
// the stack is unwound.
|
||||
//
|
||||
Throw (std::runtime_error ("pure virtual called"), fileName, lineNumber);
|
||||
}
|
||||
121
modules/beast_asio/async/SharedHandler.h
Normal file
121
modules/beast_asio/async/SharedHandler.h
Normal file
@@ -0,0 +1,121 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_ASYNC_SHAREDHANDLER_H_INCLUDED
|
||||
#define BEAST_ASIO_ASYNC_SHAREDHANDLER_H_INCLUDED
|
||||
|
||||
template <typename T>
|
||||
struct SharedHandlerAllocator;
|
||||
|
||||
/** Reference counted wrapper that can hold any other boost::asio handler.
|
||||
|
||||
This object will match these signatures:
|
||||
|
||||
@code
|
||||
|
||||
void (void)
|
||||
void (system::error_code)
|
||||
void (system::error_code, std::size_t)
|
||||
|
||||
@endcode
|
||||
|
||||
If the underlying implementation does not support the signature,
|
||||
undefined behavior will result.
|
||||
|
||||
Supports these concepts:
|
||||
Destructible
|
||||
*/
|
||||
class SharedHandler : public SharedObject
|
||||
{
|
||||
protected:
|
||||
typedef boost::system::error_code error_code;
|
||||
#if 0
|
||||
typedef boost::function <void(void)> invoked_type;
|
||||
#else
|
||||
typedef SharedFunction <void(void), SharedHandlerAllocator <char> > invoked_type;
|
||||
#endif
|
||||
|
||||
SharedHandler () noexcept { }
|
||||
|
||||
public:
|
||||
// For asio::async_result<>
|
||||
typedef void result_type;
|
||||
|
||||
typedef SharedPtr <SharedHandler> Ptr;
|
||||
|
||||
virtual void operator() ();
|
||||
virtual void operator() (error_code const&);
|
||||
virtual void operator() (error_code const&, std::size_t);
|
||||
|
||||
template <typename Function>
|
||||
void invoke (BOOST_ASIO_MOVE_ARG(Function) f)
|
||||
#if 0
|
||||
;
|
||||
#else
|
||||
{
|
||||
// The allocator will hold a reference to the SharedHandler
|
||||
// so that we can safely destroy the function object.
|
||||
invoked_type invoked (f,
|
||||
SharedHandlerAllocator <char> (this));
|
||||
invoke (invoked);
|
||||
}
|
||||
#endif
|
||||
|
||||
virtual void invoke (invoked_type& invoked) = 0;
|
||||
virtual void* allocate (std::size_t size) = 0;
|
||||
virtual void deallocate (void* p, std::size_t size) = 0;
|
||||
virtual bool is_continuation () = 0;
|
||||
|
||||
static void pure_virtual_called (char const* fileName, int lineNumber);
|
||||
|
||||
private:
|
||||
template <typename Function>
|
||||
friend void asio_handler_invoke (BOOST_ASIO_MOVE_ARG(Function) f, SharedHandler*);
|
||||
friend void* asio_handler_allocate (std::size_t, SharedHandler*);
|
||||
friend void asio_handler_deallocate (void*, std::size_t, SharedHandler*);
|
||||
friend bool asio_handler_is_continuation (SharedHandler*);
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// Context execution guarantees
|
||||
//
|
||||
|
||||
template <class Function>
|
||||
void asio_handler_invoke (BOOST_ASIO_MOVE_ARG(Function) f, SharedHandler* handler)
|
||||
{
|
||||
handler->invoke (BOOST_ASIO_MOVE_CAST(Function)(f));
|
||||
}
|
||||
|
||||
inline void* asio_handler_allocate (std::size_t size, SharedHandler* handler)
|
||||
{
|
||||
return handler->allocate (size);
|
||||
}
|
||||
|
||||
inline void asio_handler_deallocate (void* p, std::size_t size, SharedHandler* handler)
|
||||
{
|
||||
handler->deallocate (p, size);
|
||||
}
|
||||
|
||||
inline bool asio_handler_is_continuation (SharedHandler* handler)
|
||||
{
|
||||
return handler->is_continuation ();
|
||||
}
|
||||
|
||||
#endif
|
||||
127
modules/beast_asio/async/SharedHandlerAllocator.h
Normal file
127
modules/beast_asio/async/SharedHandlerAllocator.h
Normal file
@@ -0,0 +1,127 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_ASYNC_SHAREDHANDLERALLOCATOR_H_INCLUDED
|
||||
#define BEAST_ASIO_ASYNC_SHAREDHANDLERALLOCATOR_H_INCLUDED
|
||||
|
||||
/** Custom Allocator using the allocation hooks from the Handler.
|
||||
|
||||
This class is compatible with std::allocator and can be used in any
|
||||
boost interface which takes a template parameter of type Allocator.
|
||||
This includes boost::function and especially boost::asio::streambuf
|
||||
and relatives. This is vastly more efficient in a variety of situations
|
||||
especially during an upcall and when using stackful coroutines.
|
||||
|
||||
The Allocator holds a reference to the underlying SharedHandler. The
|
||||
SharedHandler will not be destroyed as long as any Allocator is still
|
||||
using it.
|
||||
*/
|
||||
template <typename T>
|
||||
struct SharedHandlerAllocator
|
||||
{
|
||||
typedef T value_type;
|
||||
typedef T* pointer;
|
||||
typedef T& reference;
|
||||
typedef T const* const_pointer;
|
||||
typedef T const& const_reference;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
|
||||
SharedHandlerAllocator (SharedHandler* handler) noexcept
|
||||
: m_ptr (handler)
|
||||
{
|
||||
}
|
||||
|
||||
SharedHandlerAllocator (SharedHandlerPtr const& handler) noexcept
|
||||
: m_ptr (handler)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
SharedHandlerAllocator (SharedHandlerAllocator <U> const& other)
|
||||
: m_ptr (other.m_ptr)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
struct rebind
|
||||
{
|
||||
typedef SharedHandlerAllocator <U> other;
|
||||
};
|
||||
|
||||
pointer address (reference x) const
|
||||
{
|
||||
return &x;
|
||||
}
|
||||
|
||||
const_pointer address (const_reference x) const
|
||||
{
|
||||
return &x;
|
||||
}
|
||||
|
||||
pointer allocate (size_type n) const
|
||||
{
|
||||
size_type const bytes = n * sizeof (value_type);
|
||||
return static_cast <pointer> (m_ptr->allocate (bytes));
|
||||
}
|
||||
|
||||
void deallocate (pointer p, size_type n) const
|
||||
{
|
||||
size_type const bytes = n * sizeof (value_type);
|
||||
m_ptr->deallocate (p, bytes);
|
||||
}
|
||||
|
||||
size_type max_size () const noexcept
|
||||
{
|
||||
return std::numeric_limits <size_type>::max () / sizeof (value_type);
|
||||
}
|
||||
|
||||
void construct (pointer p, const_reference val) const
|
||||
{
|
||||
::new ((void *)p) value_type (val);
|
||||
}
|
||||
|
||||
void destroy (pointer p) const
|
||||
{
|
||||
p->~value_type ();
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename>
|
||||
friend struct SharedHandlerAllocator;
|
||||
friend class SharedHandler;
|
||||
|
||||
SharedHandlerPtr m_ptr;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#if 0
|
||||
template <typename Function>
|
||||
void SharedHandler::invoke (BOOST_ASIO_MOVE_ARG(Function) f)
|
||||
{
|
||||
// The allocator will hold a reference to the SharedHandler
|
||||
// so that we can safely destroy the function object.
|
||||
invoked_type invoked (BOOST_ASIO_MOVE_CAST(Function)(f),
|
||||
SharedHandlerAllocator <char> (this));
|
||||
invoke (invoked);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
327
modules/beast_asio/async/SharedHandlerPtr.h
Normal file
327
modules/beast_asio/async/SharedHandlerPtr.h
Normal file
@@ -0,0 +1,327 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_ASYNC_SHAREDHANDLERPTR_H_INCLUDED
|
||||
#define BEAST_ASIO_ASYNC_SHAREDHANDLERPTR_H_INCLUDED
|
||||
|
||||
/** RAII container for a SharedHandler.
|
||||
|
||||
This object behaves exactly like a SharedHandler except that it
|
||||
merely contains a shared pointer to the underlying SharedHandler.
|
||||
All calls are forwarded to the underlying SharedHandler, and all
|
||||
of the execution safety guarantees are met by forwarding them through
|
||||
to the underlying SharedHandler.
|
||||
*/
|
||||
class SharedHandlerPtr
|
||||
{
|
||||
protected:
|
||||
typedef boost::system::error_code error_code;
|
||||
|
||||
public:
|
||||
// For asio::async_result<>
|
||||
typedef void result_type;
|
||||
|
||||
/** Construct a null handler.
|
||||
A null handler cannot be called. It can, however, be checked
|
||||
for validity by calling isNull, and later assigned.
|
||||
|
||||
@see isNull, isNotNull
|
||||
*/
|
||||
inline SharedHandlerPtr () noexcept
|
||||
{
|
||||
}
|
||||
|
||||
/** Construct from an existing SharedHandler.
|
||||
Ownership of the handler is transferred to the container.
|
||||
*/
|
||||
inline SharedHandlerPtr (SharedHandler* handler)
|
||||
: m_ptr (handler)
|
||||
{
|
||||
}
|
||||
|
||||
/** Construct a reference from an existing container.
|
||||
*/
|
||||
inline SharedHandlerPtr (SharedHandlerPtr const& other) noexcept
|
||||
: m_ptr (other.m_ptr)
|
||||
{
|
||||
}
|
||||
|
||||
/** Assign a reference from an existing container. */
|
||||
inline SharedHandlerPtr& operator= (SharedHandlerPtr const& other) noexcept
|
||||
{
|
||||
m_ptr = other.m_ptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS
|
||||
/** Move-construct a reference from an existing container.
|
||||
The other container is set to a null handler.
|
||||
*/
|
||||
inline SharedHandlerPtr (SharedHandlerPtr&& other) noexcept
|
||||
: m_ptr (other.m_ptr)
|
||||
{
|
||||
other.m_ptr = nullptr;
|
||||
}
|
||||
|
||||
/** Move-assign a reference from an existing container.
|
||||
The other container is set to a null handler.
|
||||
*/
|
||||
inline SharedHandlerPtr& operator= (SharedHandlerPtr&& other) noexcept
|
||||
{
|
||||
m_ptr = other.m_ptr;
|
||||
other.m_ptr = nullptr;
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Returns true if the handler is a null handler. */
|
||||
inline bool isNull () const noexcept
|
||||
{
|
||||
return m_ptr == nullptr;
|
||||
}
|
||||
|
||||
/** Returns true if the handler is not a null handler. */
|
||||
inline bool isNotNull () const noexcept
|
||||
{
|
||||
return m_ptr != nullptr;
|
||||
}
|
||||
|
||||
/** Dereference the container.
|
||||
This returns a reference to the underlying SharedHandler object.
|
||||
*/
|
||||
inline SharedHandler& operator* () const noexcept
|
||||
{
|
||||
return *m_ptr;
|
||||
}
|
||||
|
||||
/** SharedHandler member access.
|
||||
This lets you call functions directly on the SharedHandler.
|
||||
*/
|
||||
inline SharedHandler* operator-> () const noexcept
|
||||
{
|
||||
return m_ptr.get ();
|
||||
}
|
||||
|
||||
/** Retrieve the SharedHandler as a Context.
|
||||
|
||||
This can be used for invoking functions in the context:
|
||||
|
||||
@code
|
||||
|
||||
template <Function>
|
||||
void callOnHandler (Function f, SharedHandlerPtr ptr)
|
||||
{
|
||||
boost::asio_handler_invoke (f, ptr.get ());
|
||||
}
|
||||
|
||||
@endcode
|
||||
*/
|
||||
inline SharedHandler* get () const noexcept
|
||||
{
|
||||
return m_ptr.get ();
|
||||
}
|
||||
|
||||
/** Invoke the SharedHandler with signature void(void)
|
||||
Normally this is called by a dispatcher, you shouldn't call it directly.
|
||||
*/
|
||||
inline void operator() () const
|
||||
{
|
||||
(*m_ptr)();
|
||||
}
|
||||
|
||||
/** Invoke the SharedHandler with signature void(error_code)
|
||||
Normally this is called by a dispatcher, you shouldn't call it directly.
|
||||
*/
|
||||
inline void operator() (error_code const& ec) const
|
||||
{
|
||||
(*m_ptr)(ec);
|
||||
}
|
||||
|
||||
/** Invoke the SharedHandler with signature void(error_code, size_t)
|
||||
Normally this is called by a dispatcher, you shouldn't call it directly.
|
||||
*/
|
||||
inline void operator() (error_code const& ec, std::size_t bytes_transferred) const
|
||||
{
|
||||
(*m_ptr)(ec, bytes_transferred);
|
||||
}
|
||||
|
||||
private:
|
||||
// These ensure that SharedHandlerPtr invocations adhere to
|
||||
// the asio::io_service execution guarantees of the underlying SharedHandler.
|
||||
//
|
||||
template <typename Function>
|
||||
friend void asio_handler_invoke (BOOST_ASIO_MOVE_ARG(Function) f, SharedHandlerPtr*);
|
||||
friend void* asio_handler_allocate (std::size_t, SharedHandlerPtr*);
|
||||
friend void asio_handler_deallocate (void*, std::size_t, SharedHandlerPtr*);
|
||||
friend bool asio_handler_is_continuation (SharedHandlerPtr*);
|
||||
|
||||
SharedHandler::Ptr m_ptr;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// Context execution guarantees
|
||||
//
|
||||
|
||||
template <class Function>
|
||||
inline void asio_handler_invoke (BOOST_ASIO_MOVE_ARG(Function) f, SharedHandlerPtr* ptr)
|
||||
{
|
||||
boost_asio_handler_invoke_helpers::
|
||||
invoke <Function, SharedHandler>
|
||||
(BOOST_ASIO_MOVE_CAST(Function)(f), *ptr->get ());
|
||||
}
|
||||
|
||||
inline void* asio_handler_allocate (std::size_t size, SharedHandlerPtr* ptr)
|
||||
{
|
||||
return boost_asio_handler_alloc_helpers::
|
||||
allocate <SharedHandler> (size, *ptr->get ());
|
||||
}
|
||||
|
||||
inline void asio_handler_deallocate (void* p, std::size_t size, SharedHandlerPtr* ptr)
|
||||
{
|
||||
boost_asio_handler_alloc_helpers::
|
||||
deallocate <SharedHandler> (p, size, *ptr->get ());
|
||||
}
|
||||
|
||||
inline bool asio_handler_is_continuation (SharedHandlerPtr* ptr)
|
||||
{
|
||||
#if BEAST_ASIO_HAS_CONTINUATION_HOOKS
|
||||
return boost_asio_handler_cont_helpers::
|
||||
is_continuation <SharedHandler> (*ptr->get ());
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// Helpers
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
// void(error_code)
|
||||
template <typename Handler>
|
||||
SharedHandlerPtr newErrorHandler (
|
||||
BOOST_ASIO_MOVE_ARG(Handler) handler)
|
||||
{
|
||||
return newSharedHandlerContainer <ErrorSharedHandlerType> (
|
||||
BOOST_ASIO_MOVE_CAST(Handler)(handler));
|
||||
}
|
||||
|
||||
// void(error_code, size_t)
|
||||
template <typename Handler>
|
||||
SharedHandlerPtr newTransferHandler (
|
||||
BOOST_ASIO_MOVE_ARG(Handler) handler)
|
||||
{
|
||||
return newSharedHandlerContainer <TransferSharedHandlerType> (
|
||||
BOOST_ASIO_MOVE_CAST(Handler)(handler));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
// CompletionHandler
|
||||
//
|
||||
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/CompletionHandler.html
|
||||
//
|
||||
template <typename CompletionHandler>
|
||||
SharedHandlerPtr newCompletionHandler (
|
||||
BOOST_ASIO_MOVE_ARG(CompletionHandler) handler)
|
||||
{
|
||||
return newSharedHandlerContainer <PostSharedHandlerType> (
|
||||
BOOST_ASIO_MOVE_CAST(CompletionHandler)(handler));
|
||||
}
|
||||
|
||||
// AcceptHandler
|
||||
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/AcceptHandler.html
|
||||
//
|
||||
template <typename AcceptHandler>
|
||||
SharedHandlerPtr newAcceptHandler (
|
||||
BOOST_ASIO_MOVE_ARG(AcceptHandler) handler)
|
||||
{
|
||||
return newSharedHandlerContainer <ErrorSharedHandlerType> (
|
||||
BOOST_ASIO_MOVE_CAST(AcceptHandler)(handler));
|
||||
}
|
||||
|
||||
// ConnectHandler
|
||||
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ConnectHandler.html
|
||||
//
|
||||
template <typename ConnectHandler>
|
||||
SharedHandlerPtr newConnectHandler (
|
||||
BOOST_ASIO_MOVE_ARG(ConnectHandler) handler)
|
||||
{
|
||||
return newSharedHandlerContainer <ErrorSharedHandlerType> (
|
||||
BOOST_ASIO_MOVE_CAST(ConnectHandler)(handler));
|
||||
}
|
||||
|
||||
// ShutdownHandler
|
||||
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ShutdownHandler.html
|
||||
//
|
||||
template <typename ShutdownHandler>
|
||||
SharedHandlerPtr newShutdownHandler(
|
||||
BOOST_ASIO_MOVE_ARG(ShutdownHandler) handler)
|
||||
{
|
||||
return newSharedHandlerContainer <ErrorSharedHandlerType> (
|
||||
BOOST_ASIO_MOVE_CAST(ShutdownHandler)(handler));
|
||||
}
|
||||
|
||||
// HandshakeHandler
|
||||
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/HandshakeHandler.html
|
||||
//
|
||||
template <typename HandshakeHandler>
|
||||
SharedHandlerPtr newHandshakeHandler(
|
||||
BOOST_ASIO_MOVE_ARG(HandshakeHandler) handler)
|
||||
{
|
||||
return newSharedHandlerContainer <ErrorSharedHandlerType> (
|
||||
BOOST_ASIO_MOVE_CAST(HandshakeHandler)(handler));
|
||||
}
|
||||
|
||||
// ReadHandler
|
||||
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ReadHandler.html
|
||||
//
|
||||
template <typename ReadHandler>
|
||||
SharedHandlerPtr newReadHandler(
|
||||
BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
|
||||
{
|
||||
return newSharedHandlerContainer <TransferSharedHandlerType> (
|
||||
BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
|
||||
}
|
||||
|
||||
// WriteHandler
|
||||
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/WriteHandler.html
|
||||
//
|
||||
template <typename WriteHandler>
|
||||
SharedHandlerPtr newWriteHandler(
|
||||
BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
|
||||
{
|
||||
return newSharedHandlerContainer <TransferSharedHandlerType> (
|
||||
BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
|
||||
}
|
||||
|
||||
// BufferedHandshakeHandler
|
||||
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/BufferedHandshakeHandler.html
|
||||
//
|
||||
template <typename BufferedHandshakeHandler>
|
||||
SharedHandlerPtr newBufferedHandshakeHandler(
|
||||
BOOST_ASIO_MOVE_ARG(BufferedHandshakeHandler) handler)
|
||||
{
|
||||
return newSharedHandlerContainer <TransferSharedHandlerType> (
|
||||
BOOST_ASIO_MOVE_CAST(BufferedHandshakeHandler)(handler));
|
||||
}
|
||||
|
||||
#endif
|
||||
222
modules/beast_asio/async/SharedHandlerType.h
Normal file
222
modules/beast_asio/async/SharedHandlerType.h
Normal file
@@ -0,0 +1,222 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_ASYNC_SHAREDHANDLERTYPE_H_INCLUDED
|
||||
#define BEAST_ASIO_ASYNC_SHAREDHANDLERTYPE_H_INCLUDED
|
||||
|
||||
/** An instance of SharedHandler that wraps an existing Handler.
|
||||
|
||||
The wrapped handler will meet all the execution guarantees of
|
||||
the original Handler object.
|
||||
*/
|
||||
template <typename Handler>
|
||||
class SharedHandlerType : public SharedHandler
|
||||
{
|
||||
protected:
|
||||
SharedHandlerType (std::size_t size,
|
||||
BOOST_ASIO_MOVE_ARG(Handler) handler)
|
||||
: m_size (size)
|
||||
, m_handler (BOOST_ASIO_MOVE_CAST(Handler)(handler))
|
||||
{
|
||||
}
|
||||
|
||||
~SharedHandlerType ()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void invoke (invoked_type& invoked)
|
||||
{
|
||||
boost_asio_handler_invoke_helpers::
|
||||
invoke <invoked_type, Handler> (invoked, m_handler);
|
||||
}
|
||||
|
||||
void* allocate (std::size_t size)
|
||||
{
|
||||
return boost_asio_handler_alloc_helpers::
|
||||
allocate <Handler> (size, m_handler);
|
||||
}
|
||||
|
||||
void deallocate (void* p, std::size_t size)
|
||||
{
|
||||
boost_asio_handler_alloc_helpers::
|
||||
deallocate <Handler> (p, size, m_handler);
|
||||
}
|
||||
|
||||
bool is_continuation ()
|
||||
{
|
||||
#if BEAST_ASIO_HAS_CONTINUATION_HOOKS
|
||||
return boost_asio_handler_cont_helpers::
|
||||
is_continuation <Handler> (m_handler);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Called by SharedObject hook to destroy the object. We need
|
||||
// this because we allocated it using a custom allocator.
|
||||
// Destruction is tricky, the algorithm is as follows:
|
||||
//
|
||||
// First we move-assign the handler to our stack. If the build
|
||||
// doesn't support move-assignment it will be a copy, still ok.
|
||||
// We convert 'this' to a pointer to the polymorphic base, to
|
||||
// ensure that the following direct destructor call will reach
|
||||
// the most derived class. Finally, we deallocate the memory
|
||||
// using the handler that is local to the stack.
|
||||
//
|
||||
// For this to work we need to make sure regular operator delete
|
||||
// is never called for our object (it's private). We also need
|
||||
// the size from the original allocation, which we saved at
|
||||
// the time of construction.
|
||||
//
|
||||
void destroy ()
|
||||
{
|
||||
Handler local (BOOST_ASIO_MOVE_CAST(Handler)(m_handler));
|
||||
std::size_t const size (m_size);
|
||||
SharedHandler* const shared (static_cast <SharedHandler*>(this));
|
||||
shared->~SharedHandler ();
|
||||
boost_asio_handler_alloc_helpers::
|
||||
deallocate <Handler> (shared, size, local);
|
||||
}
|
||||
|
||||
// If these somehow get called, bad things will happen
|
||||
//
|
||||
void* operator new (std::size_t)
|
||||
{
|
||||
return pure_virtual_called (__FILE__, __LINE__);
|
||||
}
|
||||
|
||||
void operator delete (void*)
|
||||
{
|
||||
return pure_virtual_called (__FILE__, __LINE__);
|
||||
}
|
||||
|
||||
protected:
|
||||
std::size_t const m_size;
|
||||
Handler m_handler;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// A SharedHandlerType for this signature:
|
||||
// void(void)
|
||||
//
|
||||
template <typename Handler>
|
||||
class PostSharedHandlerType : public SharedHandlerType <Handler>
|
||||
{
|
||||
public:
|
||||
PostSharedHandlerType (std::size_t size,
|
||||
BOOST_ASIO_MOVE_ARG(Handler) handler)
|
||||
: SharedHandlerType <Handler> (size,
|
||||
BOOST_ASIO_MOVE_CAST(Handler)(handler))
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
void operator() ()
|
||||
{
|
||||
this->m_handler ();
|
||||
}
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// A SharedHandlerType for this signature:
|
||||
// void(error_code)
|
||||
//
|
||||
template <typename Handler>
|
||||
class ErrorSharedHandlerType : public SharedHandlerType <Handler>
|
||||
{
|
||||
public:
|
||||
ErrorSharedHandlerType (std::size_t size,
|
||||
BOOST_ASIO_MOVE_ARG(Handler) handler)
|
||||
: SharedHandlerType <Handler> (size,
|
||||
BOOST_ASIO_MOVE_CAST(Handler)(handler))
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
void operator() (boost::system::error_code const& ec)
|
||||
{
|
||||
this->m_handler (ec);
|
||||
}
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// A SharedHandlerType for this signature:
|
||||
// void(error_code, size_t)
|
||||
//
|
||||
template <typename Handler>
|
||||
class TransferSharedHandlerType : public SharedHandlerType <Handler>
|
||||
{
|
||||
public:
|
||||
TransferSharedHandlerType (std::size_t size,
|
||||
BOOST_ASIO_MOVE_ARG(Handler) handler)
|
||||
: SharedHandlerType <Handler> (size,
|
||||
BOOST_ASIO_MOVE_CAST(Handler)(handler))
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
void operator() (boost::system::error_code const& ec,
|
||||
std::size_t bytes_transferred)
|
||||
{
|
||||
this->m_handler (ec, bytes_transferred);
|
||||
}
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// These specializations will make sure we don't do
|
||||
// anything silly like wrap ourselves in our own wrapper...
|
||||
//
|
||||
#if 1
|
||||
template <>
|
||||
class PostSharedHandlerType <SharedHandler>
|
||||
{
|
||||
};
|
||||
|
||||
template <>
|
||||
class ErrorSharedHandlerType <SharedHandler>
|
||||
{
|
||||
};
|
||||
template <>
|
||||
class TransferSharedHandlerType <SharedHandler>
|
||||
{
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/** Construct a wrapped handler using the context's allocation hooks.
|
||||
*/
|
||||
template <template <typename> class Container, typename Handler>
|
||||
Container <Handler>* newSharedHandlerContainer (BOOST_ASIO_MOVE_ARG(Handler) handler)
|
||||
{
|
||||
typedef Container <Handler> ContainerType;
|
||||
std::size_t const size (sizeof (ContainerType));
|
||||
Handler local (BOOST_ASIO_MOVE_CAST(Handler)(handler));
|
||||
void* const p (boost_asio_handler_alloc_helpers::
|
||||
allocate <Handler> (size, local));
|
||||
return ::new (p) ContainerType (size, BOOST_ASIO_MOVE_CAST(Handler)(local));
|
||||
}
|
||||
|
||||
#endif
|
||||
102
modules/beast_asio/basics/BufferType.h
Normal file
102
modules/beast_asio/basics/BufferType.h
Normal file
@@ -0,0 +1,102 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_BASICS_BUFFERTYPE_H_INCLUDED
|
||||
#define BEAST_ASIO_BASICS_BUFFERTYPE_H_INCLUDED
|
||||
|
||||
/** General linear memory buffer.
|
||||
This wraps the underlying buffer type and provides additional methods
|
||||
to create a uniform interface. Specializations allow asio-compatible
|
||||
buffers without having to include boost/asio.h.
|
||||
*/
|
||||
/** @{ */
|
||||
template <bool IsConst>
|
||||
class BufferType
|
||||
{
|
||||
private:
|
||||
typedef typename mpl::IfCond <IsConst,
|
||||
void const*,
|
||||
void*>::type pointer_type;
|
||||
|
||||
typedef typename mpl::IfCond <IsConst,
|
||||
uint8 const,
|
||||
uint8>::type byte_type;
|
||||
|
||||
public:
|
||||
typedef std::size_t size_type;
|
||||
|
||||
BufferType ()
|
||||
: m_data (nullptr)
|
||||
, m_size (0)
|
||||
{
|
||||
}
|
||||
|
||||
template <bool OtherIsConst>
|
||||
BufferType (BufferType <OtherIsConst> const& other)
|
||||
: m_data (other.cast <pointer_type> ())
|
||||
, m_size (other.size ())
|
||||
{
|
||||
}
|
||||
|
||||
BufferType (pointer_type data, std::size_t size) noexcept
|
||||
: m_data (data)
|
||||
, m_size (size)
|
||||
{
|
||||
}
|
||||
|
||||
BufferType& operator= (BufferType const& other) noexcept
|
||||
{
|
||||
m_data = other.cast <pointer_type> ();
|
||||
m_size = other.size ();
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <bool OtherIsConst>
|
||||
BufferType& operator= (
|
||||
BufferType <OtherIsConst> const& other) noexcept
|
||||
{
|
||||
m_data = other.cast <pointer_type> ();
|
||||
m_size = other.size ();
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T cast () const noexcept
|
||||
{
|
||||
return static_cast <T> (m_data);
|
||||
}
|
||||
|
||||
size_type size () const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
BufferType operator+ (size_type n) const noexcept
|
||||
{
|
||||
return BufferType (cast <byte_type*> (),
|
||||
size () - std::min (size(), n));
|
||||
}
|
||||
|
||||
private:
|
||||
pointer_type m_data;
|
||||
std::size_t m_size;
|
||||
};
|
||||
/** @} */
|
||||
|
||||
#endif
|
||||
137
modules/beast_asio/basics/BuffersType.h
Normal file
137
modules/beast_asio/basics/BuffersType.h
Normal file
@@ -0,0 +1,137 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_BUFFERSTYPE_H_INCLUDED
|
||||
#define BEAST_ASIO_BUFFERSTYPE_H_INCLUDED
|
||||
|
||||
/** Storage for a BufferSequence.
|
||||
|
||||
Meets these requirements:
|
||||
BufferSequence
|
||||
ConstBufferSequence (when Buffer is mutable_buffer)
|
||||
MutableBufferSequence (when Buffer is const_buffer)
|
||||
*/
|
||||
template <class Buffer>
|
||||
class BuffersType
|
||||
{
|
||||
public:
|
||||
typedef Buffer value_type;
|
||||
typedef std::vector <Buffer> container_type;
|
||||
typedef typename container_type::const_iterator const_iterator;
|
||||
|
||||
/** Construct a null buffer.
|
||||
This is the equivalent of @ref asio::null_buffers.
|
||||
*/
|
||||
BuffersType ()
|
||||
: m_size (0)
|
||||
{
|
||||
}
|
||||
|
||||
/** Construct from a container.
|
||||
Ownership of the container is transferred, the caller's
|
||||
value becomes undefined, but valid.
|
||||
*/
|
||||
explicit BuffersType (container_type& container)
|
||||
: m_size (0)
|
||||
{
|
||||
m_buffers.swap (container);
|
||||
for (typename container_type::const_iterator iter (m_buffers.begin ());
|
||||
iter != m_buffers.end (); ++iter)
|
||||
//m_size += iter->size ();
|
||||
m_size += boost::asio::buffer_size (*iter);
|
||||
}
|
||||
|
||||
/** Construct a BuffersType from an existing BufferSequence.
|
||||
@see assign
|
||||
*/
|
||||
template <class BufferSequence>
|
||||
BuffersType (BufferSequence const& buffers)
|
||||
{
|
||||
assign (buffers);
|
||||
}
|
||||
|
||||
/** Assign a BuffersType from an existing BufferSequence.
|
||||
@see assign
|
||||
*/
|
||||
template <class BufferSequence>
|
||||
BuffersType <Buffer>& operator= (BufferSequence const& buffers)
|
||||
{
|
||||
return assign (buffers);
|
||||
}
|
||||
|
||||
/** Assign a BuffersType from an existing BufferSequence
|
||||
A copy is not made. The data is still owned by the original
|
||||
BufferSequence object. This merely points to that data.
|
||||
*/
|
||||
template <class BufferSequence>
|
||||
BuffersType <Buffer>& assign (BufferSequence const& buffers)
|
||||
{
|
||||
m_size = 0;
|
||||
m_buffers.clear ();
|
||||
m_buffers.reserve (std::distance (buffers.begin (), buffers.end ()));
|
||||
for (typename BufferSequence::const_iterator iter (
|
||||
buffers.begin ()); iter != buffers.end(); ++ iter)
|
||||
{
|
||||
//m_size += iter->size ();
|
||||
m_size += boost::asio::buffer_size (*iter);
|
||||
m_buffers.push_back (*iter);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Determine the total size of all buffers.
|
||||
This is faster than calling boost::asio::buffer_size.
|
||||
*/
|
||||
std::size_t size () const noexcept
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
const_iterator begin () const noexcept
|
||||
{
|
||||
return m_buffers.begin ();
|
||||
}
|
||||
|
||||
const_iterator end () const noexcept
|
||||
{
|
||||
return m_buffers.end ();
|
||||
}
|
||||
|
||||
private:
|
||||
std::size_t m_size;
|
||||
std::vector <Buffer> m_buffers;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** A single linear read-only buffer. */
|
||||
//typedef BufferType <true> ConstBuffer;
|
||||
typedef boost::asio::const_buffer ConstBuffer;
|
||||
|
||||
/** A single linear writable buffer. */
|
||||
//typedef BufferType <false> MutableBuffer;
|
||||
typedef boost::asio::mutable_buffer MutableBuffer;
|
||||
|
||||
/** Meets the requirements of ConstBufferSequence */
|
||||
typedef BuffersType <ConstBuffer> ConstBuffers;
|
||||
|
||||
/** Meets the requirements of MutableBufferSequence */
|
||||
typedef BuffersType <MutableBuffer> MutableBuffers;
|
||||
|
||||
#endif
|
||||
101
modules/beast_asio/basics/ContentBodyBuffer.cpp
Normal file
101
modules/beast_asio/basics/ContentBodyBuffer.cpp
Normal file
@@ -0,0 +1,101 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
ContentBodyBuffer::ContentBodyBuffer (size_type blocksize)
|
||||
: m_blocksize (blocksize)
|
||||
, m_size (0)
|
||||
{
|
||||
}
|
||||
|
||||
ContentBodyBuffer::~ContentBodyBuffer ()
|
||||
{
|
||||
for (Handles::iterator iter (m_handles.begin());
|
||||
iter != m_handles.end(); ++iter)
|
||||
{
|
||||
void* const buffer (*iter);
|
||||
std::free (buffer);
|
||||
}
|
||||
}
|
||||
|
||||
void ContentBodyBuffer::swapWith (ContentBodyBuffer& other)
|
||||
{
|
||||
std::swap (m_blocksize, other.m_blocksize);
|
||||
std::swap (m_size, other.m_size);
|
||||
m_handles.swap (other.m_handles);
|
||||
}
|
||||
|
||||
void ContentBodyBuffer::commit (size_type n)
|
||||
{
|
||||
m_size += n;
|
||||
bassert (m_size <= m_handles.size () * m_blocksize);
|
||||
}
|
||||
|
||||
ConstBuffers ContentBodyBuffer::data () const
|
||||
{
|
||||
size_type n (m_size);
|
||||
std::vector <ConstBuffer> v;
|
||||
v.reserve ((m_size + m_blocksize - 1) / m_blocksize);
|
||||
for (Handles::const_iterator iter (m_handles.begin());
|
||||
iter != m_handles.end() && n > 0; ++iter)
|
||||
{
|
||||
size_type const amount (std::min (n, m_blocksize));
|
||||
v.push_back (MutableBuffer (*iter, amount));
|
||||
n -= amount;
|
||||
}
|
||||
return ConstBuffers (v);
|
||||
}
|
||||
|
||||
ContentBodyBuffer::size_type ContentBodyBuffer::size () const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
MutableBuffers ContentBodyBuffer::prepare (size_type n)
|
||||
{
|
||||
reserve (n);
|
||||
std::vector <MutableBuffer> v;
|
||||
size_type offset (m_size % m_blocksize);
|
||||
for (Handles::iterator iter = m_handles.begin () + (m_size / m_blocksize);
|
||||
iter != m_handles.end () && n > 0; ++iter)
|
||||
{
|
||||
size_type const amount (std::min (n, m_blocksize - offset));
|
||||
v.push_back (MutableBuffer (*iter, amount));
|
||||
n -= amount;
|
||||
offset = 0;
|
||||
}
|
||||
return MutableBuffers (v);
|
||||
}
|
||||
|
||||
void ContentBodyBuffer::reserve (size_type n)
|
||||
{
|
||||
size_type count ((m_size + n + m_blocksize - 1) / m_blocksize);
|
||||
if (count > m_handles.size ())
|
||||
for (count -= m_handles.size (); count-- > 0;)
|
||||
m_handles.push_back (std::malloc (m_blocksize));
|
||||
}
|
||||
|
||||
void ContentBodyBuffer::shrink_to_fit ()
|
||||
{
|
||||
size_type const count ((m_size + m_blocksize - 1) / m_blocksize);
|
||||
while (m_handles.size () > count)
|
||||
{
|
||||
std::free (m_handles.back ());
|
||||
m_handles.erase (m_handles.end () - 1);
|
||||
}
|
||||
}
|
||||
78
modules/beast_asio/basics/ContentBodyBuffer.h
Normal file
78
modules/beast_asio/basics/ContentBodyBuffer.h
Normal file
@@ -0,0 +1,78 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_BASICS_CONTENTBODYBUFFER_H_INCLUDED
|
||||
#define BEAST_ASIO_BASICS_CONTENTBODYBUFFER_H_INCLUDED
|
||||
|
||||
/** Dynamic storage optimized for a large Content-Body of unknown size.
|
||||
This comes at the expense of discontiguous storage of the segments.
|
||||
We derive from SharedObject to make transfer of ownership inexpensive.
|
||||
*/
|
||||
class ContentBodyBuffer
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
defaultBlocksize = 32 * 1024
|
||||
};
|
||||
|
||||
typedef std::size_t size_type;
|
||||
typedef ConstBuffers const_buffers_tyoe;
|
||||
typedef MutableBuffers mutable_buffers_type;
|
||||
|
||||
explicit ContentBodyBuffer (size_type blocksize = defaultBlocksize);
|
||||
|
||||
~ContentBodyBuffer ();
|
||||
|
||||
/** Swap the contents of this buffer with another.
|
||||
This is the preferred way to transfer ownership.
|
||||
*/
|
||||
void swapWith (ContentBodyBuffer& other);
|
||||
|
||||
/** Move bytes from the output to the input sequence.
|
||||
This will invalidate references to buffers.
|
||||
*/
|
||||
void commit (size_type n);
|
||||
|
||||
/** Returns a buffer to the input sequence. */
|
||||
ConstBuffers data () const;
|
||||
|
||||
/** Returns the size of the input sequence. */
|
||||
size_type size () const;
|
||||
|
||||
/** Reserve space in the output sequence.
|
||||
This also returns a buffer suitable for writing.
|
||||
*/
|
||||
MutableBuffers prepare (size_type n);
|
||||
|
||||
/** Reserve space in the output sequence. */
|
||||
void reserve (size_type n);
|
||||
|
||||
/** Release memory while preserving the input sequence. */
|
||||
void shrink_to_fit ();
|
||||
|
||||
private:
|
||||
typedef std::vector <void*> Handles;
|
||||
|
||||
size_type m_blocksize;
|
||||
size_type m_size;
|
||||
Handles m_handles;
|
||||
};
|
||||
|
||||
#endif
|
||||
193
modules/beast_asio/basics/FixedInputBuffer.h
Normal file
193
modules/beast_asio/basics/FixedInputBuffer.h
Normal file
@@ -0,0 +1,193 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_BASICS_FIXEDINPUTBUFFER_H_INCLUDED
|
||||
#define BEAST_ASIO_BASICS_FIXEDINPUTBUFFER_H_INCLUDED
|
||||
|
||||
/** Represents a small, fixed size buffer.
|
||||
This provides a convenient interface for doing a bytewise
|
||||
verification/reject test on a handshake protocol.
|
||||
*/
|
||||
/** @{ */
|
||||
class FixedInputBuffer
|
||||
{
|
||||
protected:
|
||||
struct CtorParams
|
||||
{
|
||||
CtorParams (uint8 const* begin_, std::size_t bytes_)
|
||||
: begin (begin_)
|
||||
, bytes (bytes_)
|
||||
{
|
||||
}
|
||||
|
||||
uint8 const* begin;
|
||||
std::size_t bytes;
|
||||
};
|
||||
|
||||
FixedInputBuffer (CtorParams const& params)
|
||||
: m_begin (params.begin)
|
||||
, m_iter (m_begin)
|
||||
, m_end (m_begin + params.bytes)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
FixedInputBuffer (FixedInputBuffer const& other)
|
||||
: m_begin (other.m_begin)
|
||||
, m_iter (other.m_iter)
|
||||
, m_end (other.m_end)
|
||||
{
|
||||
}
|
||||
|
||||
FixedInputBuffer& operator= (FixedInputBuffer const& other)
|
||||
{
|
||||
m_begin = other.m_begin;
|
||||
m_iter = other.m_iter;
|
||||
m_end = other.m_end;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Returns the number of bytes consumed
|
||||
std::size_t used () const noexcept
|
||||
{
|
||||
return m_iter - m_begin;
|
||||
}
|
||||
|
||||
// Returns the size of what's remaining
|
||||
std::size_t size () const noexcept
|
||||
{
|
||||
return m_end - m_iter;
|
||||
}
|
||||
|
||||
void const* peek (std::size_t bytes)
|
||||
{
|
||||
return peek_impl (bytes, nullptr);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool peek (T* t) const noexcept
|
||||
{
|
||||
return peek_impl (sizeof (T), t) != nullptr;
|
||||
}
|
||||
|
||||
bool consume (std::size_t bytes) noexcept
|
||||
{
|
||||
return read_impl (bytes, nullptr) != nullptr;
|
||||
}
|
||||
|
||||
bool read (std::size_t bytes) noexcept
|
||||
{
|
||||
return read_impl (bytes, nullptr) != nullptr;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool read (T* t) noexcept
|
||||
{
|
||||
return read_impl (sizeof (T), t) != nullptr;
|
||||
}
|
||||
|
||||
uint8 operator[] (std::size_t index) const noexcept
|
||||
{
|
||||
bassert (index >= 0 && index < size ());
|
||||
return m_iter [index];
|
||||
}
|
||||
|
||||
// Reads an integraltype in network byte order
|
||||
template <typename IntegerType>
|
||||
bool readNetworkInteger (IntegerType* value)
|
||||
{
|
||||
// Must be an integral type!
|
||||
// not available in all versions of std:: unfortunately
|
||||
//static_bassert (std::is_integral <IntegerType>::value);
|
||||
IntegerType networkValue;
|
||||
if (! read (&networkValue))
|
||||
return false;
|
||||
*value = fromNetworkByteOrder (networkValue);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
void const* peek_impl (std::size_t bytes, void* buffer) const noexcept
|
||||
{
|
||||
if (size () >= bytes)
|
||||
{
|
||||
if (buffer != nullptr)
|
||||
memcpy (buffer, m_iter, bytes);
|
||||
return m_iter;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void const* read_impl (std::size_t bytes, void* buffer) noexcept
|
||||
{
|
||||
if (size () >= bytes)
|
||||
{
|
||||
if (buffer != nullptr)
|
||||
memcpy (buffer, m_iter, bytes);
|
||||
void const* data = m_iter;
|
||||
m_iter += bytes;
|
||||
return data;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
uint8 const* m_begin;
|
||||
uint8 const* m_iter;
|
||||
uint8 const* m_end;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <int Bytes>
|
||||
class FixedInputBufferSize : public FixedInputBuffer
|
||||
{
|
||||
protected:
|
||||
struct SizedCtorParams
|
||||
{
|
||||
template <typename ConstBufferSequence, typename Storage>
|
||||
SizedCtorParams (ConstBufferSequence const& buffers, Storage& storage)
|
||||
{
|
||||
MutableBuffer buffer (boost::asio::buffer (storage));
|
||||
data = boost::asio::buffer_cast <uint8 const*> (buffer);
|
||||
bytes = boost::asio::buffer_copy (buffer, buffers);
|
||||
}
|
||||
|
||||
operator CtorParams () const noexcept
|
||||
{
|
||||
return CtorParams (data, bytes);
|
||||
}
|
||||
|
||||
uint8 const* data;
|
||||
std::size_t bytes;
|
||||
};
|
||||
|
||||
public:
|
||||
template <typename ConstBufferSequence>
|
||||
explicit FixedInputBufferSize (ConstBufferSequence const& buffers)
|
||||
: FixedInputBuffer (SizedCtorParams (buffers, m_storage))
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
boost::array <uint8, Bytes> m_storage;
|
||||
MutableBuffer m_buffer;
|
||||
};
|
||||
|
||||
#endif
|
||||
44
modules/beast_asio/basics/PeerRole.cpp
Normal file
44
modules/beast_asio/basics/PeerRole.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
PeerRole::PeerRole (role_t role)
|
||||
: m_role (role)
|
||||
{
|
||||
}
|
||||
|
||||
String PeerRole::name () const noexcept
|
||||
{
|
||||
if (m_role == server)
|
||||
return "server";
|
||||
return "client";
|
||||
}
|
||||
|
||||
bool PeerRole::operator== (role_t role) const noexcept
|
||||
{
|
||||
return m_role == role;
|
||||
}
|
||||
|
||||
#if 0
|
||||
PeerRole::operator Socket::handshake_type () const noexcept
|
||||
{
|
||||
if (m_role == server)
|
||||
return Socket::server;
|
||||
return Socket::client;
|
||||
}
|
||||
#endif
|
||||
40
modules/beast_asio/basics/PeerRole.h
Normal file
40
modules/beast_asio/basics/PeerRole.h
Normal file
@@ -0,0 +1,40 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_BASICS_PEERROLE_H_INCLUDED
|
||||
#define BEAST_ASIO_BASICS_PEERROLE_H_INCLUDED
|
||||
|
||||
/** Identifies if the peer is a client or a server. */
|
||||
struct PeerRole
|
||||
{
|
||||
enum role_t
|
||||
{
|
||||
client,
|
||||
server
|
||||
};
|
||||
|
||||
PeerRole (role_t role);
|
||||
String name () const noexcept;
|
||||
bool operator== (role_t role) const noexcept;
|
||||
|
||||
private:
|
||||
role_t m_role;
|
||||
};
|
||||
|
||||
#endif
|
||||
28
modules/beast_asio/basics/SSLContext.cpp
Normal file
28
modules/beast_asio/basics/SSLContext.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
SSLContext::SSLContext (ContextType& context)
|
||||
: m_context (context)
|
||||
{
|
||||
}
|
||||
|
||||
SSLContext::~SSLContext ()
|
||||
{
|
||||
}
|
||||
|
||||
61
modules/beast_asio/basics/SSLContext.h
Normal file
61
modules/beast_asio/basics/SSLContext.h
Normal file
@@ -0,0 +1,61 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_BASICS_SSLCONTEXT_H_INCLUDED
|
||||
#define BEAST_ASIO_BASICS_SSLCONTEXT_H_INCLUDED
|
||||
|
||||
/** Simple base class for passing a context around.
|
||||
This lets derived classes hide their implementation from the headers.
|
||||
*/
|
||||
class SSLContext : public Uncopyable
|
||||
{
|
||||
public:
|
||||
virtual ~SSLContext ();
|
||||
|
||||
// Saves typing
|
||||
typedef boost::asio::ssl::context ContextType;
|
||||
|
||||
inline ContextType& get () noexcept
|
||||
{
|
||||
return m_context;
|
||||
}
|
||||
|
||||
inline ContextType const& get () const noexcept
|
||||
{
|
||||
return m_context;
|
||||
}
|
||||
|
||||
// implicit conversion
|
||||
inline operator ContextType& () noexcept
|
||||
{
|
||||
return get ();
|
||||
}
|
||||
|
||||
inline operator ContextType const& () const noexcept
|
||||
{
|
||||
return get ();
|
||||
}
|
||||
|
||||
protected:
|
||||
explicit SSLContext (ContextType& context);
|
||||
|
||||
ContextType& m_context;
|
||||
};
|
||||
|
||||
#endif
|
||||
75
modules/beast_asio/beast_asio.cpp
Normal file
75
modules/beast_asio/beast_asio.cpp
Normal file
@@ -0,0 +1,75 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include "BeastConfig.h"
|
||||
|
||||
#include "system/OpenSSLIncludes.h"
|
||||
|
||||
#include "beast_asio.h"
|
||||
|
||||
namespace beast
|
||||
{
|
||||
|
||||
#include "async/SharedHandler.cpp"
|
||||
|
||||
#include "basics/ContentBodyBuffer.cpp"
|
||||
#include "basics/PeerRole.cpp"
|
||||
#include "basics/SSLContext.cpp"
|
||||
|
||||
#include "sockets/SocketBase.cpp"
|
||||
#include "sockets/Socket.cpp"
|
||||
|
||||
#include "protocol/HandshakeDetectLogicPROXY.cpp"
|
||||
|
||||
# include "parsehttp/http_parser.h"
|
||||
# include "http/HTTPParserImpl.h"
|
||||
#include "http/HTTPParser.cpp"
|
||||
#include "http/UniformResourceLocator.cpp"
|
||||
#include "http/HTTPClientType.cpp"
|
||||
#include "http/HTTPField.cpp"
|
||||
#include "http/HTTPHeaders.cpp"
|
||||
#include "http/HTTPMessage.cpp"
|
||||
#include "http/HTTPResponse.cpp"
|
||||
#include "http/HTTPVersion.cpp"
|
||||
|
||||
#include "tests/PeerTest.cpp"
|
||||
#include "tests/TestPeerBasics.cpp"
|
||||
#include "tests/TestPeerLogic.cpp"
|
||||
#include "tests/TestPeerLogicProxyClient.cpp"
|
||||
#include "tests/TestPeerLogicSyncServer.cpp"
|
||||
#include "tests/TestPeerLogicSyncClient.cpp"
|
||||
#include "tests/TestPeerLogicAsyncServer.cpp"
|
||||
#include "tests/TestPeerLogicAsyncClient.cpp"
|
||||
#include "tests/TestPeerUnitTests.cpp"
|
||||
|
||||
#include "system/BoostUnitTests.cpp"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable: 4127) // conditional expression is constant
|
||||
#pragma warning (disable: 4244) // integer conversion, possible loss of data
|
||||
#endif
|
||||
#include "parsehttp/http_parser.c"
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (pop)
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
111
modules/beast_asio/beast_asio.h
Normal file
111
modules/beast_asio/beast_asio.h
Normal file
@@ -0,0 +1,111 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_H_INCLUDED
|
||||
#define BEAST_ASIO_H_INCLUDED
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/* If you fail to make sure that all your compile units are building Beast with
|
||||
the same set of option flags, then there's a risk that different compile
|
||||
units will treat the classes as having different memory layouts, leading to
|
||||
very nasty memory corruption errors when they all get linked together.
|
||||
That's why it's best to always include the BeastConfig.h file before any
|
||||
beast headers.
|
||||
*/
|
||||
#ifndef BEAST_BEASTCONFIG_H_INCLUDED
|
||||
# ifdef _MSC_VER
|
||||
# pragma message ("Have you included your BeastConfig.h file before including the Beast headers?")
|
||||
# else
|
||||
# warning "Have you included your BeastConfig.h file before including the Beast headers?"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// Must come before boost includes to fix the bost placeholders.
|
||||
#include "../beast_core/beast_core.h"
|
||||
|
||||
// This module requires boost and possibly OpenSSL
|
||||
#include "system/BoostIncludes.h"
|
||||
|
||||
// Checking overrides replaces unimplemented stubs with pure virtuals
|
||||
#ifndef BEAST_COMPILER_CHECKS_SOCKET_OVERRIDES
|
||||
# define BEAST_COMPILER_CHECKS_SOCKET_OVERRIDES 0
|
||||
#endif
|
||||
#if BEAST_COMPILER_CHECKS_SOCKET_OVERRIDES
|
||||
# define BEAST_SOCKET_VIRTUAL = 0
|
||||
#else
|
||||
# define BEAST_SOCKET_VIRTUAL
|
||||
#endif
|
||||
|
||||
namespace beast
|
||||
{
|
||||
|
||||
// Order matters
|
||||
# include "async/SharedHandler.h"
|
||||
# include "async/SharedHandlerType.h"
|
||||
# include "async/SharedHandlerPtr.h"
|
||||
# include "async/ComposedAsyncOperation.h"
|
||||
#include "async/SharedHandlerAllocator.h"
|
||||
|
||||
# include "basics/BufferType.h"
|
||||
# include "basics/BuffersType.h"
|
||||
#include "basics/ContentBodyBuffer.h"
|
||||
#include "basics/FixedInputBuffer.h"
|
||||
#include "basics/PeerRole.h"
|
||||
#include "basics/SSLContext.h"
|
||||
|
||||
# include "sockets/SocketBase.h"
|
||||
# include "sockets/Socket.h"
|
||||
# include "sockets/SocketWrapper.h"
|
||||
#include "sockets/SocketWrapperStrand.h"
|
||||
|
||||
# include "http/HTTPVersion.h"
|
||||
# include "http/HTTPField.h"
|
||||
# include "http/HTTPHeaders.h"
|
||||
# include "http/HTTPMessage.h"
|
||||
# include "http/HTTPResponse.h"
|
||||
# include "http/HTTPParser.h"
|
||||
# include "http/UniformResourceLocator.h"
|
||||
#include "http/HTTPClientType.h"
|
||||
|
||||
# include "protocol/InputParser.h"
|
||||
# include "protocol/HandshakeDetectLogic.h"
|
||||
#include "protocol/HandshakeDetectLogicPROXY.h"
|
||||
#include "protocol/HandshakeDetectLogicSSL2.h"
|
||||
#include "protocol/HandshakeDetectLogicSSL3.h"
|
||||
#include "protocol/HandshakeDetector.h"
|
||||
#include "protocol/PrefilledReadStream.h"
|
||||
|
||||
#include "tests/TestPeerBasics.h"
|
||||
#include "tests/TestPeer.h"
|
||||
#include "tests/TestPeerDetails.h"
|
||||
#include "tests/TestPeerLogic.h"
|
||||
#include "tests/TestPeerLogicSyncServer.h"
|
||||
#include "tests/TestPeerLogicSyncClient.h"
|
||||
#include "tests/TestPeerLogicProxyClient.h"
|
||||
#include "tests/TestPeerLogicAsyncServer.h"
|
||||
#include "tests/TestPeerLogicAsyncClient.h"
|
||||
#include "tests/TestPeerType.h"
|
||||
#include "tests/TestPeerDetailsTcp.h"
|
||||
#include "tests/PeerTest.h"
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
838
modules/beast_asio/http/HTTPClientType.cpp
Normal file
838
modules/beast_asio/http/HTTPClientType.cpp
Normal file
@@ -0,0 +1,838 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
class HTTPClientType : public HTTPClientBase, public Uncopyable
|
||||
{
|
||||
private:
|
||||
using HTTPClientBase::Listener;
|
||||
|
||||
typedef boost::system::error_code error_code;
|
||||
|
||||
class ListenerHandler
|
||||
{
|
||||
public:
|
||||
ListenerHandler ()
|
||||
: m_owner (nullptr)
|
||||
, m_listener (nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
ListenerHandler (HTTPClientType* owner, Listener* listener = nullptr)
|
||||
: m_owner (owner)
|
||||
, m_listener (listener)
|
||||
{
|
||||
}
|
||||
|
||||
ListenerHandler (ListenerHandler const& other)
|
||||
: m_owner (other.m_owner)
|
||||
, m_listener (other.m_listener)
|
||||
{
|
||||
}
|
||||
|
||||
ListenerHandler& operator= (ListenerHandler const& other)
|
||||
{
|
||||
m_owner = other.m_owner;
|
||||
m_listener = other.m_listener;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void operator() (error_code)
|
||||
{
|
||||
if (m_listener != nullptr)
|
||||
m_listener->onHTTPRequestComplete (
|
||||
*m_owner, m_owner->result ());
|
||||
}
|
||||
|
||||
private:
|
||||
HTTPClientType* m_owner;
|
||||
Listener* m_listener;
|
||||
};
|
||||
|
||||
public:
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
HTTPClientType (
|
||||
double timeoutSeconds,
|
||||
std::size_t messageLimitBytes,
|
||||
std::size_t bufferSize)
|
||||
: m_timeoutSeconds (timeoutSeconds)
|
||||
, m_messageLimitBytes (messageLimitBytes)
|
||||
, m_bufferSize (bufferSize)
|
||||
{
|
||||
}
|
||||
|
||||
~HTTPClientType ()
|
||||
{
|
||||
m_async_op = nullptr;
|
||||
}
|
||||
|
||||
Result const& result () const
|
||||
{
|
||||
return m_result;
|
||||
}
|
||||
|
||||
Result const& get (UniformResourceLocator const& url)
|
||||
{
|
||||
boost::asio::io_service io_service;
|
||||
async_get (io_service, nullptr, url);
|
||||
io_service.run ();
|
||||
cancel ();
|
||||
return result ();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void async_get (boost::asio::io_service& io_service, Listener* listener,
|
||||
UniformResourceLocator const& url)
|
||||
{
|
||||
async_get (io_service, url, ListenerHandler (this, listener));
|
||||
}
|
||||
|
||||
// Handler signature is void(error_code)
|
||||
//
|
||||
template <typename Handler>
|
||||
void async_get (boost::asio::io_service& io_service,
|
||||
UniformResourceLocator const& url,
|
||||
BOOST_ASIO_MOVE_ARG(Handler) handler)
|
||||
{
|
||||
async_get (io_service, url, newErrorHandler (
|
||||
BOOST_ASIO_MOVE_CAST(Handler)(handler)));
|
||||
}
|
||||
|
||||
void async_get (boost::asio::io_service& io_service,
|
||||
UniformResourceLocator const& url, SharedHandlerPtr handler)
|
||||
{
|
||||
// This automatically dispatches
|
||||
m_async_op = new AsyncGetOp (
|
||||
*this, io_service, url, handler,
|
||||
m_timeoutSeconds, m_messageLimitBytes, m_bufferSize);
|
||||
}
|
||||
|
||||
void cancel ()
|
||||
{
|
||||
if (m_async_op != nullptr)
|
||||
{
|
||||
m_async_op->cancel ();
|
||||
m_async_op = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/** Helper function to get a const_buffer from a String. */
|
||||
static boost::asio::const_buffers_1 stringBuffer (String const& s)
|
||||
{
|
||||
return boost::asio::const_buffers_1 (s.getCharPointer (), s.length ());
|
||||
}
|
||||
|
||||
/** Helper function to fill out a Query from a URL. */
|
||||
template <typename Query>
|
||||
static Query queryFromURL (UniformResourceLocator const& url)
|
||||
{
|
||||
if (url.port () != 0)
|
||||
{
|
||||
return Query (
|
||||
url.host().toStdString(),
|
||||
url.port_string().toStdString(),
|
||||
Query::numeric_service);
|
||||
}
|
||||
|
||||
return Query (
|
||||
url.host().toStdString(),
|
||||
url.scheme().toStdString());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
class AsyncGetOp : public ComposedAsyncOperation
|
||||
{
|
||||
private:
|
||||
typedef boost::asio::ip::tcp Protocol;
|
||||
typedef boost::system::error_code error_code;
|
||||
|
||||
typedef Protocol::resolver resolver;
|
||||
typedef resolver::query query;
|
||||
typedef resolver::iterator iterator;
|
||||
typedef iterator::value_type resolver_entry;
|
||||
typedef Protocol::socket socket;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
enum State
|
||||
{
|
||||
stateStart,
|
||||
stateResolveComplete,
|
||||
stateConnectComplete,
|
||||
stateHandshakeComplete,
|
||||
stateWriteComplete,
|
||||
stateShutdownComplete
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
struct TimerHandler : SharedHandlerPtr
|
||||
{
|
||||
explicit TimerHandler (AsyncGetOp* owner)
|
||||
: SharedHandlerPtr (owner)
|
||||
, m_owner (owner)
|
||||
{
|
||||
}
|
||||
void operator() (error_code const& ec)
|
||||
{
|
||||
m_owner->timerCompletion (ec);
|
||||
}
|
||||
|
||||
AsyncGetOp* m_owner;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
public:
|
||||
AsyncGetOp (HTTPClientType& owner,
|
||||
boost::asio::io_service& io_service,
|
||||
UniformResourceLocator const& url,
|
||||
SharedHandlerPtr const& handler,
|
||||
double timeoutSeconds,
|
||||
std::size_t messageLimitBytes,
|
||||
std::size_t bufferSize)
|
||||
: ComposedAsyncOperation (sizeof (*this), handler)
|
||||
, m_owner (owner)
|
||||
, m_io_service (io_service)
|
||||
, m_strand (m_io_service)
|
||||
, m_url (url)
|
||||
, m_handler (handler)
|
||||
, m_timer (io_service)
|
||||
, m_resolver (io_service)
|
||||
, m_socket (io_service)
|
||||
, m_context (boost::asio::ssl::context::sslv23)
|
||||
, m_buffer (bufferSize)
|
||||
, m_parser (HTTPParser::typeResponse)
|
||||
, m_timer_canceled (false)
|
||||
, m_timer_expired (false)
|
||||
, m_messageLimitBytes (messageLimitBytes)
|
||||
, m_bytesReceived (0)
|
||||
{
|
||||
m_context.set_default_verify_paths ();
|
||||
m_context.set_options (
|
||||
boost::asio::ssl::context::no_sslv2 |
|
||||
boost::asio::ssl::context::single_dh_use |
|
||||
boost::asio::ssl::context::default_workarounds);
|
||||
//m_context.set_verify_mode (boost::asio::ssl::verify_peer);
|
||||
|
||||
if (timeoutSeconds > 0)
|
||||
{
|
||||
m_timer.expires_from_now (
|
||||
boost::posix_time::milliseconds (
|
||||
long (timeoutSeconds * 1000)));
|
||||
|
||||
++m_io_pending;
|
||||
m_timer.async_wait (TimerHandler (this));
|
||||
}
|
||||
|
||||
// Count as pending i/o
|
||||
++m_io_pending;
|
||||
m_io_service.dispatch (
|
||||
m_strand.wrap (StartHandler (this)));
|
||||
}
|
||||
|
||||
~AsyncGetOp ()
|
||||
{
|
||||
}
|
||||
|
||||
// Cancel all pending I/O, if any, and block until
|
||||
// there are no more completion handler calls pending.
|
||||
//
|
||||
void cancel ()
|
||||
{
|
||||
cancel_all ();
|
||||
m_done.wait ();
|
||||
}
|
||||
|
||||
private:
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
// Counts a pending i/o as canceled
|
||||
//
|
||||
void cancel_io ()
|
||||
{
|
||||
bassert (m_io_pending.get () > 0);
|
||||
if (--m_io_pending == 0)
|
||||
m_done.signal ();
|
||||
}
|
||||
|
||||
// Cancels the deadline timer.
|
||||
//
|
||||
void cancel_timer ()
|
||||
{
|
||||
m_timer_canceled = true;
|
||||
error_code ec;
|
||||
m_timer.cancel (ec);
|
||||
}
|
||||
|
||||
// Called to notify the original handler the operation is complete.
|
||||
//
|
||||
void complete (error_code const& ec)
|
||||
{
|
||||
m_owner.m_result.error = ec;
|
||||
|
||||
cancel_timer ();
|
||||
|
||||
bassert (m_io_pending.get () > 0);
|
||||
|
||||
cancel_io ();
|
||||
|
||||
// We call the handler directly since we know
|
||||
// we are already in the right context, and
|
||||
// because we need to do some things afterwards.
|
||||
//
|
||||
m_handler->operator() (ec);
|
||||
}
|
||||
|
||||
// Called every time an async operation completes.
|
||||
// The return value indicates if the handler should
|
||||
// stop additional activity and return immediately.
|
||||
//
|
||||
bool io_complete (error_code const& ec)
|
||||
{
|
||||
if (m_timer_expired ||
|
||||
ec == boost::asio::error::operation_aborted)
|
||||
{
|
||||
cancel_io ();
|
||||
return true;
|
||||
}
|
||||
else if (ec != 0 && ec != boost::asio::error::eof)
|
||||
{
|
||||
complete (ec);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Cancels/closes all i/o objects.
|
||||
//
|
||||
void cancel_all ()
|
||||
{
|
||||
cancel_timer ();
|
||||
m_resolver.cancel ();
|
||||
error_code ec;
|
||||
m_socket.close (ec);
|
||||
}
|
||||
|
||||
// Called when the deadline timer expires or is canceled.
|
||||
//
|
||||
void timerCompletion (error_code ec)
|
||||
{
|
||||
if (ec == boost::asio::error::operation_aborted)
|
||||
{
|
||||
bassert (m_timer_canceled);
|
||||
return cancel_io ();
|
||||
}
|
||||
|
||||
check_invariant (ec == 0);
|
||||
|
||||
// Handle the case where the timer completion has already
|
||||
// been queued for dispatch but we have finished the operation
|
||||
// and queued the completion handler for dispatch.
|
||||
//
|
||||
if (! m_timer_canceled)
|
||||
{
|
||||
m_timer_expired = true;
|
||||
|
||||
ec = error_code (boost::asio::error::timed_out,
|
||||
boost::asio::error::get_system_category ());
|
||||
|
||||
complete (ec);
|
||||
|
||||
io_complete (ec);
|
||||
|
||||
m_resolver.cancel ();
|
||||
m_socket.close (ec);
|
||||
}
|
||||
else
|
||||
{
|
||||
cancel_io ();
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
struct StartHandler : SharedHandlerPtr
|
||||
{
|
||||
explicit StartHandler (AsyncGetOp* owner)
|
||||
: SharedHandlerPtr (owner)
|
||||
, m_owner (owner)
|
||||
{
|
||||
}
|
||||
|
||||
void operator() ()
|
||||
{
|
||||
m_owner->start_complete ();
|
||||
}
|
||||
|
||||
AsyncGetOp* m_owner;
|
||||
};
|
||||
|
||||
struct ResolveHandler : SharedHandlerPtr
|
||||
{
|
||||
explicit ResolveHandler (AsyncGetOp* owner)
|
||||
: SharedHandlerPtr (owner)
|
||||
, m_owner (owner)
|
||||
{
|
||||
}
|
||||
|
||||
void operator() (error_code const& ec, iterator iter)
|
||||
{
|
||||
m_owner->resolve_complete (ec, iter);
|
||||
}
|
||||
|
||||
AsyncGetOp* m_owner;
|
||||
};
|
||||
|
||||
struct ConnectHandler : SharedHandlerPtr
|
||||
{
|
||||
explicit ConnectHandler (AsyncGetOp* owner)
|
||||
: SharedHandlerPtr (owner)
|
||||
, m_owner (owner)
|
||||
{
|
||||
}
|
||||
|
||||
void operator() (error_code const& ec)
|
||||
{
|
||||
m_owner->connect_complete (ec);
|
||||
}
|
||||
|
||||
AsyncGetOp* m_owner;
|
||||
};
|
||||
|
||||
struct HandshakeHandler : SharedHandlerPtr
|
||||
{
|
||||
explicit HandshakeHandler (AsyncGetOp* owner)
|
||||
: SharedHandlerPtr (owner)
|
||||
, m_owner (owner)
|
||||
{
|
||||
}
|
||||
|
||||
void operator() (error_code const& ec)
|
||||
{
|
||||
m_owner->handshake_complete (ec);
|
||||
}
|
||||
|
||||
AsyncGetOp* m_owner;
|
||||
};
|
||||
|
||||
struct WriteHandler : SharedHandlerPtr
|
||||
{
|
||||
explicit WriteHandler (AsyncGetOp* owner)
|
||||
: SharedHandlerPtr (owner)
|
||||
, m_owner (owner)
|
||||
{
|
||||
}
|
||||
|
||||
void operator() (error_code const& ec, std::size_t bytes_transferred)
|
||||
{
|
||||
m_owner->write_complete (ec, bytes_transferred);
|
||||
}
|
||||
|
||||
AsyncGetOp* m_owner;
|
||||
};
|
||||
|
||||
struct ReadHandler : SharedHandlerPtr
|
||||
{
|
||||
explicit ReadHandler (AsyncGetOp* owner)
|
||||
: SharedHandlerPtr (owner)
|
||||
, m_owner (owner)
|
||||
{
|
||||
}
|
||||
|
||||
void operator() (error_code const& ec, std::size_t bytes_transferred)
|
||||
{
|
||||
m_owner->read_complete (ec, bytes_transferred);
|
||||
}
|
||||
|
||||
AsyncGetOp* m_owner;
|
||||
};
|
||||
|
||||
struct ShutdownHandler : SharedHandlerPtr
|
||||
{
|
||||
explicit ShutdownHandler (AsyncGetOp* owner)
|
||||
: SharedHandlerPtr (owner)
|
||||
, m_owner (owner)
|
||||
{
|
||||
}
|
||||
|
||||
void operator() (error_code const& ec)
|
||||
{
|
||||
m_owner->shutdown_complete (ec);
|
||||
}
|
||||
|
||||
AsyncGetOp* m_owner;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
void async_read_some ()
|
||||
{
|
||||
boost::asio::mutable_buffers_1 buf (
|
||||
m_buffer.getData (), m_buffer.getSize ());
|
||||
|
||||
m_stream->async_read_some (buf,
|
||||
m_strand.wrap (ReadHandler (this)));
|
||||
}
|
||||
|
||||
// Called when the HTTP parser returns an error
|
||||
void parse_error ()
|
||||
{
|
||||
//unsigned char const http_errno (m_parser.error ());
|
||||
String const http_errmsg (m_parser.message ());
|
||||
|
||||
// VFALCO TODO put the parser error in ec
|
||||
error_code ec (
|
||||
boost::system::errc::invalid_argument,
|
||||
boost::system::system_category ());
|
||||
|
||||
complete (ec);
|
||||
}
|
||||
|
||||
// Called to create an error when the message is over the limit
|
||||
error_code message_limit_error ()
|
||||
{
|
||||
// VFALCO TODO Make a suitable error code
|
||||
return error_code (
|
||||
boost::system::errc::invalid_argument,
|
||||
boost::system::system_category ());
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
void start_complete ()
|
||||
{
|
||||
query q (queryFromURL <query> (m_url));
|
||||
m_resolver.async_resolve (q,
|
||||
m_strand.wrap (ResolveHandler (this)));
|
||||
}
|
||||
|
||||
void resolve_complete (error_code ec, iterator iter)
|
||||
{
|
||||
if (io_complete (ec))
|
||||
return;
|
||||
|
||||
resolver_entry const entry (*iter);
|
||||
m_socket.async_connect (entry.endpoint (),
|
||||
m_strand.wrap (ConnectHandler (this)));
|
||||
}
|
||||
|
||||
void connect_complete (error_code ec)
|
||||
{
|
||||
if (io_complete (ec))
|
||||
return;
|
||||
|
||||
if (m_url.scheme () == "https")
|
||||
{
|
||||
typedef boost::asio::ssl::stream <socket&> ssl_stream;
|
||||
m_stream = new SocketWrapper <ssl_stream> (m_socket, m_context);
|
||||
/*
|
||||
m_stream->set_verify_mode (
|
||||
boost::asio::ssl::verify_peer |
|
||||
boost::asio::ssl::verify_fail_if_no_peer_cert);
|
||||
*/
|
||||
m_stream->async_handshake (
|
||||
Socket::client, HandshakeHandler (this));
|
||||
return;
|
||||
}
|
||||
|
||||
m_stream = new SocketWrapper <socket&> (m_socket);
|
||||
handshake_complete (ec);
|
||||
}
|
||||
|
||||
void handshake_complete (error_code ec)
|
||||
{
|
||||
if (io_complete (ec))
|
||||
return;
|
||||
|
||||
m_get_string =
|
||||
"GET " + m_url.path() + " HTTP/1.1\r\n" +
|
||||
"Host: " + m_url.host() + "\r\n" +
|
||||
"Accept: */*\r\n" +
|
||||
"Connection: close\r\n\r\n";
|
||||
|
||||
boost::asio::async_write (
|
||||
*m_stream, stringBuffer (m_get_string),
|
||||
m_strand.wrap (WriteHandler (this)));
|
||||
++m_io_pending;
|
||||
|
||||
async_read_some ();
|
||||
}
|
||||
|
||||
void write_complete (error_code ec, std::size_t)
|
||||
{
|
||||
if (io_complete (ec))
|
||||
return;
|
||||
|
||||
if (! m_stream->needs_handshake ())
|
||||
{
|
||||
m_socket.shutdown (socket::shutdown_send, ec);
|
||||
if (ec != 0)
|
||||
return complete (ec);
|
||||
}
|
||||
|
||||
// deduct one i/o since we aren't issuing any new one
|
||||
cancel_io ();
|
||||
}
|
||||
|
||||
void read_complete (error_code ec, std::size_t bytes_transferred)
|
||||
{
|
||||
m_bytesReceived += bytes_transferred;
|
||||
if (m_bytesReceived > m_messageLimitBytes)
|
||||
ec = message_limit_error ();
|
||||
|
||||
if (io_complete (ec))
|
||||
return;
|
||||
|
||||
std::size_t const bytes_parsed (m_parser.process (
|
||||
m_buffer.getData (), bytes_transferred));
|
||||
|
||||
if (m_parser.error ())
|
||||
{
|
||||
parse_error ();
|
||||
return;
|
||||
}
|
||||
|
||||
if (bytes_parsed != bytes_transferred)
|
||||
{
|
||||
// VFALCO TODO put an appropriate error in ec
|
||||
ec = error_code (
|
||||
boost::system::errc::invalid_argument,
|
||||
boost::system::system_category ());
|
||||
return complete (ec);
|
||||
}
|
||||
|
||||
if (ec == boost::asio::error::eof)
|
||||
{
|
||||
m_parser.process_eof ();
|
||||
}
|
||||
|
||||
if (m_parser.finished ())
|
||||
{
|
||||
m_state = stateShutdownComplete;
|
||||
if (m_stream->needs_handshake ())
|
||||
m_stream->async_shutdown (ShutdownHandler (this));
|
||||
else
|
||||
shutdown_complete (error_code ());
|
||||
return;
|
||||
}
|
||||
|
||||
async_read_some ();
|
||||
}
|
||||
|
||||
void shutdown_complete (error_code ec)
|
||||
{
|
||||
if (io_complete (ec))
|
||||
return;
|
||||
|
||||
m_owner.m_result.response = m_parser.response ();
|
||||
if (ec == boost::asio::error::eof)
|
||||
ec = error_code ();
|
||||
|
||||
return complete (ec);
|
||||
}
|
||||
|
||||
private:
|
||||
WaitableEvent m_done;
|
||||
Atomic <int> m_io_pending;
|
||||
HTTPClientType& m_owner;
|
||||
boost::asio::io_service& m_io_service;
|
||||
boost::asio::io_service& m_strand;
|
||||
UniformResourceLocator m_url;
|
||||
SharedHandlerPtr m_handler;
|
||||
boost::asio::deadline_timer m_timer;
|
||||
resolver m_resolver;
|
||||
socket m_socket;
|
||||
ScopedPointer <Socket> m_stream;
|
||||
boost::asio::ssl::context m_context;
|
||||
MemoryBlock m_buffer;
|
||||
State m_state;
|
||||
HTTPParser m_parser;
|
||||
String m_get_string;
|
||||
bool m_timer_canceled;
|
||||
bool m_timer_expired;
|
||||
std::size_t m_messageLimitBytes;
|
||||
std::size_t m_bytesReceived;
|
||||
};
|
||||
|
||||
double m_timeoutSeconds;
|
||||
std::size_t m_messageLimitBytes;
|
||||
std::size_t m_bufferSize;
|
||||
boost::asio::io_service m_io_service;
|
||||
SharedPtr <AsyncGetOp> m_async_op;
|
||||
Result m_result;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
HTTPClientBase* HTTPClientBase::New (
|
||||
double timeoutSeconds, std::size_t messageLimitBytes, std::size_t bufferSize)
|
||||
{
|
||||
ScopedPointer <HTTPClientBase> object (new HTTPClientType
|
||||
(timeoutSeconds, messageLimitBytes, bufferSize));
|
||||
return object.release ();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class HTTPClientTests
|
||||
: public UnitTest
|
||||
, public HTTPClientBase::Listener
|
||||
{
|
||||
public:
|
||||
typedef boost::system::error_code error_code;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
class IoServiceThread : protected Thread
|
||||
{
|
||||
public:
|
||||
explicit IoServiceThread (String name = "io_service")
|
||||
: Thread (name)
|
||||
{
|
||||
}
|
||||
|
||||
~IoServiceThread ()
|
||||
{
|
||||
join ();
|
||||
}
|
||||
|
||||
boost::asio::io_service& get_io_service ()
|
||||
{
|
||||
return m_service;
|
||||
}
|
||||
|
||||
void start ()
|
||||
{
|
||||
startThread ();
|
||||
}
|
||||
|
||||
void join ()
|
||||
{
|
||||
this->waitForThreadToExit ();
|
||||
}
|
||||
|
||||
private:
|
||||
void run ()
|
||||
{
|
||||
m_service.run ();
|
||||
}
|
||||
|
||||
private:
|
||||
boost::asio::io_service m_service;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void log (HTTPMessage const& m)
|
||||
{
|
||||
for (std::size_t i = 0; i < m.headers().size(); ++i)
|
||||
{
|
||||
HTTPField const f (m.headers()[i]);
|
||||
String s;
|
||||
s = "[ '" + f.name() +
|
||||
"' , '" + f.value() + "' ]";
|
||||
logMessage (s);
|
||||
}
|
||||
}
|
||||
|
||||
void log (HTTPClientBase::Result const& result)
|
||||
{
|
||||
if (result.error != 0)
|
||||
{
|
||||
logMessage (String (
|
||||
"HTTPClient error: '" + result.error.message() + "'"));
|
||||
}
|
||||
else if (! result.response.empty ())
|
||||
{
|
||||
logMessage (String ("Status: ") +
|
||||
String::fromNumber (result.response->status()));
|
||||
|
||||
log (*result.response);
|
||||
}
|
||||
else
|
||||
{
|
||||
logMessage ("HTTPClient: no response");
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void onHTTPRequestComplete (
|
||||
HTTPClientBase const&, HTTPClientBase::Result const& result)
|
||||
{
|
||||
log (result);
|
||||
}
|
||||
|
||||
void testSync (String const& s, double timeoutSeconds)
|
||||
{
|
||||
ScopedPointer <HTTPClientBase> client (
|
||||
HTTPClientBase::New (timeoutSeconds));
|
||||
|
||||
log (client->get (ParsedURL (s).url ()));
|
||||
}
|
||||
|
||||
void testAsync (String const& s, double timeoutSeconds)
|
||||
{
|
||||
IoServiceThread t;
|
||||
ScopedPointer <HTTPClientBase> client (
|
||||
HTTPClientBase::New (timeoutSeconds));
|
||||
|
||||
client->async_get (t.get_io_service (), this,
|
||||
ParsedURL (s).url ());
|
||||
|
||||
t.start ();
|
||||
t.join ();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void runTest ()
|
||||
{
|
||||
beginTestCase ("HTTPClient::get");
|
||||
|
||||
testSync (
|
||||
"http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference.html",
|
||||
5);
|
||||
|
||||
testAsync (
|
||||
"http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference.html",
|
||||
5);
|
||||
|
||||
testAsync (
|
||||
"https://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference.html",
|
||||
5);
|
||||
|
||||
pass ();
|
||||
}
|
||||
|
||||
HTTPClientTests () : UnitTest ("HttpClient", "beast", runManual)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
static HTTPClientTests httpClientTests;
|
||||
|
||||
|
||||
65
modules/beast_asio/http/HTTPClientType.h
Normal file
65
modules/beast_asio/http/HTTPClientType.h
Normal file
@@ -0,0 +1,65 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_HTTPCLIENTTYPE_H_INCLUDED
|
||||
#define BEAST_ASIO_HTTPCLIENTTYPE_H_INCLUDED
|
||||
|
||||
class HTTPClientBase
|
||||
{
|
||||
public:
|
||||
struct Result
|
||||
{
|
||||
boost::system::error_code error;
|
||||
SharedPtr <HTTPResponse> response;
|
||||
};
|
||||
|
||||
class Listener
|
||||
{
|
||||
public:
|
||||
virtual void onHTTPRequestComplete (
|
||||
HTTPClientBase const& client,
|
||||
Result const& result) = 0;
|
||||
};
|
||||
|
||||
static HTTPClientBase* New (
|
||||
double timeoutSeconds = 30,
|
||||
std::size_t messageLimitBytes = 256 * 1024,
|
||||
std::size_t bufferSize = 16 * 1024);
|
||||
|
||||
virtual ~HTTPClientBase () { }
|
||||
|
||||
virtual Result const& result () const = 0;
|
||||
|
||||
virtual Result const& get (
|
||||
UniformResourceLocator const& url) = 0;
|
||||
|
||||
virtual void async_get (boost::asio::io_service& io_service,
|
||||
Listener* listener,
|
||||
UniformResourceLocator const& url) = 0;
|
||||
|
||||
/** Cancel any pending asynchronous operations.
|
||||
This must be called before destroying the container if there are
|
||||
any pending asynchronous operations. This routine does nothing if
|
||||
there are no pending operations. The call will block until all
|
||||
pending i/o is canceled.
|
||||
*/
|
||||
virtual void cancel () = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
51
modules/beast_asio/http/HTTPField.cpp
Normal file
51
modules/beast_asio/http/HTTPField.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
HTTPField::HTTPField ()
|
||||
{
|
||||
}
|
||||
|
||||
HTTPField::HTTPField (String name_, String value_)
|
||||
: m_name (name_)
|
||||
, m_value (value_)
|
||||
{
|
||||
}
|
||||
|
||||
HTTPField::HTTPField (HTTPField const& other)
|
||||
: m_name (other.m_name)
|
||||
, m_value (other.m_value)
|
||||
{
|
||||
}
|
||||
|
||||
HTTPField& HTTPField::operator= (HTTPField const& other)
|
||||
{
|
||||
m_name = other.m_name;
|
||||
m_value = other.m_value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
String HTTPField::name () const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
String HTTPField::value () const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
42
modules/beast_asio/http/HTTPField.h
Normal file
42
modules/beast_asio/http/HTTPField.h
Normal file
@@ -0,0 +1,42 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_HTTPFIELD_H_INCLUDED
|
||||
#define BEAST_ASIO_HTTPFIELD_H_INCLUDED
|
||||
|
||||
/** A single header.
|
||||
The header is a field/value pair.
|
||||
Time complexity of copies is constant.
|
||||
*/
|
||||
class HTTPField
|
||||
{
|
||||
public:
|
||||
HTTPField ();
|
||||
HTTPField (String name_, String value_);
|
||||
HTTPField (HTTPField const& other);
|
||||
HTTPField& operator= (HTTPField const& other);
|
||||
String name () const;
|
||||
String value () const;
|
||||
|
||||
private:
|
||||
String m_name;
|
||||
String m_value;
|
||||
};
|
||||
|
||||
#endif
|
||||
74
modules/beast_asio/http/HTTPHeaders.cpp
Normal file
74
modules/beast_asio/http/HTTPHeaders.cpp
Normal file
@@ -0,0 +1,74 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
HTTPHeaders::HTTPHeaders ()
|
||||
{
|
||||
}
|
||||
|
||||
HTTPHeaders::HTTPHeaders (StringPairArray& fields)
|
||||
{
|
||||
m_fields.swapWith (fields);
|
||||
}
|
||||
|
||||
HTTPHeaders::HTTPHeaders (StringPairArray const& fields)
|
||||
: m_fields (fields)
|
||||
{
|
||||
}
|
||||
|
||||
HTTPHeaders::HTTPHeaders (HTTPHeaders const& other)
|
||||
: m_fields (other.m_fields)
|
||||
{
|
||||
}
|
||||
|
||||
HTTPHeaders& HTTPHeaders::operator= (HTTPHeaders const& other)
|
||||
{
|
||||
m_fields = other.m_fields;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool HTTPHeaders::empty () const
|
||||
{
|
||||
return m_fields.size () == 0;
|
||||
}
|
||||
|
||||
std::size_t HTTPHeaders::size () const
|
||||
{
|
||||
return m_fields.size ();
|
||||
}
|
||||
|
||||
HTTPField HTTPHeaders::at (std::size_t index) const
|
||||
{
|
||||
return HTTPField (m_fields.getAllKeys () [index],
|
||||
m_fields.getAllValues () [index]);
|
||||
}
|
||||
|
||||
HTTPField HTTPHeaders::operator[] (std::size_t index) const
|
||||
{
|
||||
return at (index);
|
||||
}
|
||||
|
||||
String HTTPHeaders::get (String const& field) const
|
||||
{
|
||||
return m_fields [field];
|
||||
}
|
||||
|
||||
String HTTPHeaders::operator[] (String const& field) const
|
||||
{
|
||||
return get (field);
|
||||
}
|
||||
68
modules/beast_asio/http/HTTPHeaders.h
Normal file
68
modules/beast_asio/http/HTTPHeaders.h
Normal file
@@ -0,0 +1,68 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_HTTPHEADERS_H_INCLUDED
|
||||
#define BEAST_ASIO_HTTPHEADERS_H_INCLUDED
|
||||
|
||||
/** A set of HTTP headers. */
|
||||
class HTTPHeaders
|
||||
{
|
||||
public:
|
||||
/** Construct an empty set of headers. */
|
||||
HTTPHeaders ();
|
||||
|
||||
/** Construct headers taking ownership of a field array.
|
||||
The callers value is overwritten.
|
||||
*/
|
||||
HTTPHeaders (StringPairArray& fields);
|
||||
|
||||
/** Construct a copy of headers from an array.*/
|
||||
HTTPHeaders (StringPairArray const& fields);
|
||||
|
||||
/** Construct a copy of headers. */
|
||||
HTTPHeaders (HTTPHeaders const& other);
|
||||
|
||||
/** Assign a copy of headers. */
|
||||
HTTPHeaders& operator= (HTTPHeaders const& other);
|
||||
|
||||
/** Returns `true` if the container is empty. */
|
||||
bool empty () const;
|
||||
|
||||
/** Returns the number of fields in the container. */
|
||||
std::size_t size () const;
|
||||
|
||||
/** Random access to fields by index. */
|
||||
/** @{ */
|
||||
HTTPField at (std::size_t index) const;
|
||||
HTTPField operator[] (std::size_t index) const;
|
||||
/** @} */
|
||||
|
||||
/** Associative access to fields by name.
|
||||
If the field is not present, an empty string is returned.
|
||||
*/
|
||||
/** @{ */
|
||||
String get (String const& field) const;
|
||||
String operator[] (String const& field) const;
|
||||
/** @} */
|
||||
|
||||
private:
|
||||
StringPairArray m_fields;
|
||||
};
|
||||
|
||||
#endif
|
||||
42
modules/beast_asio/http/HTTPMessage.cpp
Normal file
42
modules/beast_asio/http/HTTPMessage.cpp
Normal file
@@ -0,0 +1,42 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
HTTPMessage::HTTPMessage (HTTPVersion const& version_,
|
||||
StringPairArray& fields,
|
||||
ContentBodyBuffer& body)
|
||||
: m_version (version_)
|
||||
, m_headers (fields)
|
||||
{
|
||||
m_body.swapWith (body);
|
||||
}
|
||||
|
||||
HTTPVersion const& HTTPMessage::version () const
|
||||
{
|
||||
return m_version;
|
||||
}
|
||||
|
||||
HTTPHeaders const& HTTPMessage::headers () const
|
||||
{
|
||||
return m_headers;
|
||||
}
|
||||
|
||||
ContentBodyBuffer const& HTTPMessage::body () const
|
||||
{
|
||||
return m_body;
|
||||
}
|
||||
60
modules/beast_asio/http/HTTPMessage.h
Normal file
60
modules/beast_asio/http/HTTPMessage.h
Normal file
@@ -0,0 +1,60 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_HTTPMESSAGE_H_INCLUDED
|
||||
#define BEAST_ASIO_HTTPMESSAGE_H_INCLUDED
|
||||
|
||||
/** A complete HTTP message.
|
||||
|
||||
This provides the information common to all HTTP messages, including
|
||||
the version, content body, and headers.
|
||||
Derived classes provide the request or response specific data.
|
||||
|
||||
Because a single HTTP message can be a fairly expensive object to
|
||||
make copies of, this is a SharedObject.
|
||||
|
||||
@see HTTPRequest, HTTPResponse
|
||||
*/
|
||||
class HTTPMessage : public SharedObject
|
||||
{
|
||||
public:
|
||||
/** Construct the common HTTP message parts from values.
|
||||
Ownership of the fields and body parameters are
|
||||
transferred from the caller.
|
||||
*/
|
||||
HTTPMessage (HTTPVersion const& version_,
|
||||
StringPairArray& fields,
|
||||
ContentBodyBuffer& body);
|
||||
|
||||
/** Returns the HTTP version of this message. */
|
||||
HTTPVersion const& version () const;
|
||||
|
||||
/** Returns the set of HTTP headers associated with this message. */
|
||||
HTTPHeaders const& headers () const;
|
||||
|
||||
/** Returns the content-body. */
|
||||
ContentBodyBuffer const& body () const;
|
||||
|
||||
private:
|
||||
HTTPVersion m_version;
|
||||
HTTPHeaders m_headers;
|
||||
ContentBodyBuffer m_body;
|
||||
};
|
||||
|
||||
#endif
|
||||
79
modules/beast_asio/http/HTTPParser.cpp
Normal file
79
modules/beast_asio/http/HTTPParser.cpp
Normal file
@@ -0,0 +1,79 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
HTTPParser::HTTPParser (Type type)
|
||||
: m_type (type)
|
||||
, m_impl (new HTTPParserImpl (
|
||||
(type == typeResponse) ? HTTP_RESPONSE : HTTP_REQUEST))
|
||||
{
|
||||
}
|
||||
|
||||
HTTPParser::~HTTPParser ()
|
||||
{
|
||||
}
|
||||
|
||||
unsigned char HTTPParser::error () const
|
||||
{
|
||||
return m_impl->http_errno ();
|
||||
}
|
||||
|
||||
String HTTPParser::message () const
|
||||
{
|
||||
return m_impl->http_errno_message ();
|
||||
}
|
||||
|
||||
std::size_t HTTPParser::process (void const* buf, std::size_t bytes)
|
||||
{
|
||||
std::size_t const bytes_used (m_impl->process (buf, bytes));
|
||||
|
||||
if (m_impl->finished ())
|
||||
{
|
||||
if (m_type == typeResponse)
|
||||
{
|
||||
m_response = new HTTPResponse (
|
||||
m_impl->version (),
|
||||
m_impl->fields (),
|
||||
m_impl->body (),
|
||||
m_impl->status_code ());
|
||||
}
|
||||
else
|
||||
{
|
||||
// m_request = new HTTPRequest (
|
||||
}
|
||||
}
|
||||
|
||||
return bytes_used;
|
||||
}
|
||||
|
||||
void HTTPParser::process_eof ()
|
||||
{
|
||||
m_impl->process_eof ();
|
||||
}
|
||||
|
||||
bool HTTPParser::finished () const
|
||||
{
|
||||
return m_impl->finished();
|
||||
}
|
||||
|
||||
SharedPtr <HTTPResponse> const& HTTPParser::response ()
|
||||
{
|
||||
bassert (m_type == typeResponse);
|
||||
|
||||
return m_response;
|
||||
}
|
||||
74
modules/beast_asio/http/HTTPParser.h
Normal file
74
modules/beast_asio/http/HTTPParser.h
Normal file
@@ -0,0 +1,74 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_HTTPPARSER_H_INCLUDED
|
||||
#define BEAST_ASIO_HTTPPARSER_H_INCLUDED
|
||||
|
||||
class HTTPParserImpl;
|
||||
|
||||
/** A parser for HTTPRequest and HTTPResponse objects. */
|
||||
class HTTPParser
|
||||
{
|
||||
public:
|
||||
enum Type
|
||||
{
|
||||
typeRequest,
|
||||
typeResponse
|
||||
};
|
||||
|
||||
/** Construct a new parser for the specified HTTPMessage type. */
|
||||
explicit HTTPParser (Type type);
|
||||
|
||||
/** Destroy the parser. */
|
||||
~HTTPParser ();
|
||||
|
||||
/** Returns a non zero error code if parsing fails. */
|
||||
unsigned char error () const;
|
||||
|
||||
/** Returns the error message text when error is non zero. */
|
||||
String message () const;
|
||||
|
||||
/** Parse the buffer and return the amount used.
|
||||
Typically it is an error when this returns less than
|
||||
the amount passed in.
|
||||
*/
|
||||
std::size_t process (void const* buf, std::size_t bytes);
|
||||
|
||||
/** Notify the parser that eof was received.
|
||||
*/
|
||||
void process_eof ();
|
||||
|
||||
/** Returns `true` when parsing is successful and complete. */
|
||||
bool finished () const;
|
||||
|
||||
/** Return the HTTPResponse object produce from the parsing.
|
||||
Only valid after finished returns `true`.
|
||||
*/
|
||||
SharedPtr <HTTPResponse> const& response ();
|
||||
|
||||
//SharedPtr <HTTPRequest> const& request ();
|
||||
|
||||
private:
|
||||
Type m_type;
|
||||
ScopedPointer <HTTPParserImpl> m_impl;
|
||||
SharedPtr <HTTPResponse> m_response;
|
||||
//SharedPtr <HTTPRequest> m_request;
|
||||
};
|
||||
|
||||
#endif
|
||||
256
modules/beast_asio/http/HTTPParserImpl.h
Normal file
256
modules/beast_asio/http/HTTPParserImpl.h
Normal file
@@ -0,0 +1,256 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_HTTPPARSERIMPL_H_INCLUDED
|
||||
#define BEAST_HTTPPARSERIMPL_H_INCLUDED
|
||||
|
||||
class HTTPParserImpl
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
stringReservation = 256
|
||||
};
|
||||
|
||||
explicit HTTPParserImpl (enum http_parser_type type)
|
||||
: m_finished (false)
|
||||
, m_was_value (false)
|
||||
{
|
||||
m_settings.on_message_begin = &HTTPParserImpl::on_message_begin;
|
||||
m_settings.on_url = &HTTPParserImpl::on_url;
|
||||
m_settings.on_status_complete = &HTTPParserImpl::on_status_complete;
|
||||
m_settings.on_header_field = &HTTPParserImpl::on_header_field;
|
||||
m_settings.on_header_value = &HTTPParserImpl::on_header_value;
|
||||
m_settings.on_headers_complete = &HTTPParserImpl::on_headers_complete;
|
||||
m_settings.on_body = &HTTPParserImpl::on_body;
|
||||
m_settings.on_message_complete = &HTTPParserImpl::on_message_complete;
|
||||
|
||||
m_field.reserve (stringReservation);
|
||||
m_value.reserve (stringReservation);
|
||||
|
||||
http_parser_init (&m_parser, type);
|
||||
m_parser.data = this;
|
||||
}
|
||||
|
||||
~HTTPParserImpl ()
|
||||
{
|
||||
}
|
||||
|
||||
unsigned char error () const
|
||||
{
|
||||
return m_parser.http_errno;
|
||||
}
|
||||
|
||||
String message () const
|
||||
{
|
||||
return String (http_errno_name (static_cast <
|
||||
enum http_errno> (m_parser.http_errno)));
|
||||
}
|
||||
|
||||
std::size_t process (void const* buf, std::size_t bytes)
|
||||
{
|
||||
return http_parser_execute (&m_parser,
|
||||
&m_settings, static_cast <char const*> (buf), bytes);
|
||||
}
|
||||
|
||||
void process_eof ()
|
||||
{
|
||||
http_parser_execute (&m_parser, &m_settings, nullptr, 0);
|
||||
}
|
||||
|
||||
bool finished () const
|
||||
{
|
||||
return m_finished;
|
||||
}
|
||||
|
||||
HTTPVersion version () const
|
||||
{
|
||||
return HTTPVersion (
|
||||
m_parser.http_major, m_parser.http_minor);
|
||||
}
|
||||
|
||||
// Only for HTTPResponse!
|
||||
unsigned short status_code () const
|
||||
{
|
||||
return m_parser.status_code;
|
||||
}
|
||||
|
||||
// Only for HTTPRequest!
|
||||
unsigned char method () const
|
||||
{
|
||||
return m_parser.method;
|
||||
}
|
||||
|
||||
unsigned char http_errno () const
|
||||
{
|
||||
return m_parser.http_errno;
|
||||
}
|
||||
|
||||
String http_errno_message () const
|
||||
{
|
||||
return String (http_errno_name (
|
||||
static_cast <enum http_errno> (
|
||||
m_parser.http_errno)));
|
||||
}
|
||||
|
||||
bool upgrade () const
|
||||
{
|
||||
return m_parser.upgrade != 0;
|
||||
}
|
||||
|
||||
StringPairArray& fields ()
|
||||
{
|
||||
return m_fields;
|
||||
}
|
||||
|
||||
ContentBodyBuffer& body ()
|
||||
{
|
||||
return m_body;
|
||||
}
|
||||
|
||||
private:
|
||||
void addFieldValue ()
|
||||
{
|
||||
if (m_field.size () > 0 && m_value.size () > 0)
|
||||
m_fields.set (m_field, m_value);
|
||||
m_field.resize (0);
|
||||
m_value.resize (0);
|
||||
}
|
||||
|
||||
int onMessageBegin ()
|
||||
{
|
||||
int ec (0);
|
||||
return ec;
|
||||
}
|
||||
|
||||
int onUrl (char const*, std::size_t)
|
||||
{
|
||||
int ec (0);
|
||||
// This is for HTTP Request
|
||||
return ec;
|
||||
}
|
||||
|
||||
int onStatusComplete ()
|
||||
{
|
||||
int ec (0);
|
||||
return ec;
|
||||
}
|
||||
|
||||
int onHeaderField (char const* at, std::size_t length)
|
||||
{
|
||||
int ec (0);
|
||||
if (m_was_value)
|
||||
{
|
||||
addFieldValue ();
|
||||
m_was_value = false;
|
||||
}
|
||||
m_field.append (at, length);
|
||||
return ec;
|
||||
}
|
||||
|
||||
int onHeaderValue (char const* at, std::size_t length)
|
||||
{
|
||||
int ec (0);
|
||||
m_value.append (at, length);
|
||||
m_was_value = true;
|
||||
return ec;
|
||||
}
|
||||
|
||||
int onHeadersComplete ()
|
||||
{
|
||||
int ec (0);
|
||||
addFieldValue ();
|
||||
return ec;
|
||||
}
|
||||
|
||||
int onBody (char const* at, std::size_t length)
|
||||
{
|
||||
m_body.commit (boost::asio::buffer_copy (m_body.prepare (length),
|
||||
boost::asio::buffer (at, length)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int onMessageComplete ()
|
||||
{
|
||||
int ec (0);
|
||||
m_finished = true;
|
||||
return ec;
|
||||
}
|
||||
|
||||
private:
|
||||
static int on_message_begin (http_parser* parser)
|
||||
{
|
||||
return static_cast <HTTPParserImpl*> (parser->data)->
|
||||
onMessageBegin ();
|
||||
}
|
||||
|
||||
static int on_url (http_parser* parser, const char *at, size_t length)
|
||||
{
|
||||
return static_cast <HTTPParserImpl*> (parser->data)->
|
||||
onUrl (at, length);
|
||||
}
|
||||
|
||||
static int on_status_complete (http_parser* parser)
|
||||
{
|
||||
return static_cast <HTTPParserImpl*> (parser->data)->
|
||||
onStatusComplete ();
|
||||
}
|
||||
|
||||
static int on_header_field (http_parser* parser, const char *at, size_t length)
|
||||
{
|
||||
return static_cast <HTTPParserImpl*> (parser->data)->
|
||||
onHeaderField (at, length);
|
||||
}
|
||||
|
||||
static int on_header_value (http_parser* parser, const char *at, size_t length)
|
||||
{
|
||||
return static_cast <HTTPParserImpl*> (parser->data)->
|
||||
onHeaderValue (at, length);
|
||||
}
|
||||
|
||||
static int on_headers_complete (http_parser* parser)
|
||||
{
|
||||
return static_cast <HTTPParserImpl*> (parser->data)->
|
||||
onHeadersComplete ();
|
||||
}
|
||||
|
||||
static int on_body (http_parser* parser, const char *at, size_t length)
|
||||
{
|
||||
return static_cast <HTTPParserImpl*> (parser->data)->
|
||||
onBody (at, length);
|
||||
}
|
||||
|
||||
static int on_message_complete (http_parser* parser)
|
||||
{
|
||||
return static_cast <HTTPParserImpl*> (parser->data)->
|
||||
onMessageComplete ();
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_finished;
|
||||
http_parser_settings m_settings;
|
||||
http_parser m_parser;
|
||||
StringPairArray m_fields;
|
||||
bool m_was_value;
|
||||
std::string m_field;
|
||||
std::string m_value;
|
||||
ContentBodyBuffer m_body;
|
||||
};
|
||||
|
||||
#endif
|
||||
33
modules/beast_asio/http/HTTPResponse.cpp
Normal file
33
modules/beast_asio/http/HTTPResponse.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
HTTPResponse::HTTPResponse (
|
||||
HTTPVersion const& version_,
|
||||
StringPairArray& fields,
|
||||
ContentBodyBuffer& body,
|
||||
unsigned short status_)
|
||||
: HTTPMessage (version_, fields, body)
|
||||
, m_status (status_)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned short HTTPResponse::status () const
|
||||
{
|
||||
return m_status;
|
||||
}
|
||||
42
modules/beast_asio/http/HTTPResponse.h
Normal file
42
modules/beast_asio/http/HTTPResponse.h
Normal file
@@ -0,0 +1,42 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_HTTPRESPONSE_H_INCLUDED
|
||||
#define BEAST_ASIO_HTTPRESPONSE_H_INCLUDED
|
||||
|
||||
class HTTPResponse : public HTTPMessage
|
||||
{
|
||||
public:
|
||||
/** Construct a complete response from values.
|
||||
Ownership of the fields and body parameters are
|
||||
transferred from the caller.
|
||||
*/
|
||||
HTTPResponse (
|
||||
HTTPVersion const& version_,
|
||||
StringPairArray& fields,
|
||||
ContentBodyBuffer& body,
|
||||
unsigned short status_);
|
||||
|
||||
unsigned short status () const;
|
||||
|
||||
private:
|
||||
unsigned short m_status;
|
||||
};
|
||||
|
||||
#endif
|
||||
93
modules/beast_asio/http/HTTPVersion.cpp
Normal file
93
modules/beast_asio/http/HTTPVersion.cpp
Normal file
@@ -0,0 +1,93 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
HTTPVersion::HTTPVersion ()
|
||||
: m_major (0)
|
||||
, m_minor (0)
|
||||
{
|
||||
}
|
||||
|
||||
HTTPVersion::HTTPVersion (unsigned short major_, unsigned short minor_)
|
||||
: m_major (major_)
|
||||
, m_minor (minor_)
|
||||
{
|
||||
}
|
||||
|
||||
HTTPVersion::HTTPVersion (HTTPVersion const& other)
|
||||
: m_major (other.m_major)
|
||||
, m_minor (other.m_minor)
|
||||
{
|
||||
}
|
||||
|
||||
HTTPVersion& HTTPVersion::operator= (HTTPVersion const& other)
|
||||
{
|
||||
m_major = other.m_major;
|
||||
m_minor = other.m_minor;
|
||||
return *this;
|
||||
}
|
||||
|
||||
String HTTPVersion::toString () const
|
||||
{
|
||||
return String::fromNumber (major ()) + "." +
|
||||
String::fromNumber (minor ());
|
||||
}
|
||||
|
||||
unsigned short HTTPVersion::major () const
|
||||
{
|
||||
return m_major;
|
||||
}
|
||||
|
||||
unsigned short HTTPVersion::minor () const
|
||||
{
|
||||
return m_minor;
|
||||
}
|
||||
|
||||
bool HTTPVersion::operator== (HTTPVersion const& rhs) const
|
||||
{
|
||||
return (m_major == rhs.m_major) && (m_minor == rhs.m_minor);
|
||||
}
|
||||
|
||||
bool HTTPVersion::operator!= (HTTPVersion const& rhs) const
|
||||
{
|
||||
return (m_major != rhs.m_major) || (m_minor != rhs.m_minor);
|
||||
}
|
||||
|
||||
bool HTTPVersion::operator> (HTTPVersion const& rhs) const
|
||||
{
|
||||
return (m_major > rhs.m_major) ||
|
||||
((m_major == rhs.m_major) && (m_minor > rhs.m_minor));
|
||||
}
|
||||
|
||||
bool HTTPVersion::operator>= (HTTPVersion const& rhs) const
|
||||
{
|
||||
return (m_major > rhs.m_major) ||
|
||||
((m_major == rhs.m_major) && (m_minor >= rhs.m_minor));
|
||||
}
|
||||
|
||||
bool HTTPVersion::operator< (HTTPVersion const& rhs) const
|
||||
{
|
||||
return (m_major < rhs.m_major) ||
|
||||
((m_major == rhs.m_major) && (m_minor < rhs.m_minor));
|
||||
}
|
||||
|
||||
bool HTTPVersion::operator<= (HTTPVersion const& rhs) const
|
||||
{
|
||||
return (m_major < rhs.m_major) ||
|
||||
((m_major == rhs.m_major) && (m_minor <= rhs.m_minor));
|
||||
}
|
||||
46
modules/beast_asio/http/HTTPVersion.h
Normal file
46
modules/beast_asio/http/HTTPVersion.h
Normal file
@@ -0,0 +1,46 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_HTTPVERSION_H_INCLUDED
|
||||
#define BEAST_ASIO_HTTPVERSION_H_INCLUDED
|
||||
|
||||
/** The HTTP version. This is the major.minor version number. */
|
||||
class HTTPVersion
|
||||
{
|
||||
public:
|
||||
HTTPVersion ();
|
||||
HTTPVersion (unsigned short major_, unsigned short minor_);
|
||||
HTTPVersion (HTTPVersion const& other);
|
||||
HTTPVersion& operator= (HTTPVersion const& other);
|
||||
String toString () const;
|
||||
unsigned short major () const;
|
||||
unsigned short minor () const;
|
||||
bool operator== (HTTPVersion const& rhs) const;
|
||||
bool operator!= (HTTPVersion const& rhs) const;
|
||||
bool operator> (HTTPVersion const& rhs) const;
|
||||
bool operator>= (HTTPVersion const& rhs) const;
|
||||
bool operator< (HTTPVersion const& rhs) const;
|
||||
bool operator<= (HTTPVersion const& rhs) const;
|
||||
|
||||
private:
|
||||
unsigned short m_major;
|
||||
unsigned short m_minor;;
|
||||
};
|
||||
|
||||
#endif
|
||||
299
modules/beast_asio/http/UniformResourceLocator.cpp
Normal file
299
modules/beast_asio/http/UniformResourceLocator.cpp
Normal file
@@ -0,0 +1,299 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
UniformResourceLocator::UniformResourceLocator ()
|
||||
: m_port (0)
|
||||
{
|
||||
}
|
||||
|
||||
UniformResourceLocator::UniformResourceLocator (
|
||||
String scheme_,
|
||||
String host_,
|
||||
uint16 port_,
|
||||
String port_string_,
|
||||
String path_,
|
||||
String query_,
|
||||
String fragment_,
|
||||
String userinfo_)
|
||||
: m_scheme (scheme_)
|
||||
, m_host (host_)
|
||||
, m_port (port_)
|
||||
, m_port_string (port_string_)
|
||||
, m_path (path_)
|
||||
, m_query (query_)
|
||||
, m_fragment (fragment_)
|
||||
, m_userinfo (userinfo_)
|
||||
{
|
||||
}
|
||||
|
||||
UniformResourceLocator::UniformResourceLocator (UniformResourceLocator const& other)
|
||||
: m_scheme (other.m_scheme)
|
||||
, m_host (other.m_host)
|
||||
, m_port (other.m_port)
|
||||
, m_port_string (other.m_port_string)
|
||||
, m_path (other.m_path)
|
||||
, m_query (other.m_query)
|
||||
, m_fragment (other.m_fragment)
|
||||
, m_userinfo (other.m_userinfo)
|
||||
{
|
||||
}
|
||||
|
||||
UniformResourceLocator& UniformResourceLocator::operator= (UniformResourceLocator const& other)
|
||||
{
|
||||
m_scheme = other.m_scheme;
|
||||
m_host = other.m_host;
|
||||
m_port = other.m_port;
|
||||
m_port_string = other.m_port_string;
|
||||
m_path = other.m_path;
|
||||
m_query = other.m_query;
|
||||
m_fragment = other.m_fragment;
|
||||
m_userinfo = other.m_userinfo;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
String UniformResourceLocator::scheme () const
|
||||
{
|
||||
return m_scheme;
|
||||
}
|
||||
|
||||
String UniformResourceLocator::host () const
|
||||
{
|
||||
return m_host;
|
||||
}
|
||||
|
||||
String UniformResourceLocator::port_string () const
|
||||
{
|
||||
return m_port_string;
|
||||
}
|
||||
|
||||
uint16 UniformResourceLocator::port () const
|
||||
{
|
||||
return m_port;
|
||||
}
|
||||
|
||||
String UniformResourceLocator::path () const
|
||||
{
|
||||
return m_path;
|
||||
}
|
||||
|
||||
String UniformResourceLocator::query () const
|
||||
{
|
||||
return m_query;
|
||||
}
|
||||
|
||||
String UniformResourceLocator::fragment () const
|
||||
{
|
||||
return m_fragment;
|
||||
}
|
||||
|
||||
String UniformResourceLocator::userinfo () const
|
||||
{
|
||||
return m_userinfo;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
From
|
||||
http://en.wikipedia.org/wiki/URI_scheme
|
||||
|
||||
<scheme name> : <hierarchical part> [ ? <query> ] [ # <fragment> ]
|
||||
|
||||
e.g.
|
||||
|
||||
foo://username:password@example.com:8042/over/there/index.dtb?type=animal&name=narwhal#nose
|
||||
*/
|
||||
String UniformResourceLocator::full () const
|
||||
{
|
||||
String s;
|
||||
|
||||
s = scheme () + "://";
|
||||
|
||||
if (userinfo () != String::empty)
|
||||
s = userinfo () + "@";
|
||||
|
||||
s = s + host ();
|
||||
|
||||
if (port () != 0)
|
||||
s = s + ":" + String::fromNumber (port ());
|
||||
|
||||
s = s + path ();
|
||||
|
||||
if (query () != String::empty)
|
||||
s = "?" + query ();
|
||||
|
||||
if (fragment () != String::empty)
|
||||
s = "#" + fragment ();
|
||||
|
||||
return s;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
ParsedURL::ParsedURL ()
|
||||
: m_error (0)
|
||||
{
|
||||
}
|
||||
|
||||
ParsedURL::ParsedURL (String const& url)
|
||||
{
|
||||
std::string const ss (url.toStdString ());
|
||||
std::size_t const buflen (ss.size ());
|
||||
char const* const buf (ss.c_str ());
|
||||
|
||||
http_parser_url u;
|
||||
|
||||
m_error = http_parser_parse_url (buf, buflen, false, &u);
|
||||
|
||||
String scheme_;
|
||||
String host_;
|
||||
uint16 port_ (0);
|
||||
String port_string_;
|
||||
String path_;
|
||||
String query_;
|
||||
String fragment_;
|
||||
String userinfo_;
|
||||
|
||||
if (m_error == 0)
|
||||
{
|
||||
if ((u.field_set & (1<<UF_SCHEMA)) != 0)
|
||||
{
|
||||
scheme_ = String (
|
||||
buf + u.field_data [UF_SCHEMA].off,
|
||||
u.field_data [UF_SCHEMA].len);
|
||||
}
|
||||
|
||||
if ((u.field_set & (1<<UF_HOST)) != 0)
|
||||
{
|
||||
host_ = String (
|
||||
buf + u.field_data [UF_HOST].off,
|
||||
u.field_data [UF_HOST].len);
|
||||
}
|
||||
|
||||
if ((u.field_set & (1<<UF_PORT)) != 0)
|
||||
{
|
||||
port_ = u.port;
|
||||
port_string_ = String (
|
||||
buf + u.field_data [UF_PORT].off,
|
||||
u.field_data [UF_PORT].len);
|
||||
}
|
||||
else
|
||||
{
|
||||
port_ = 0;
|
||||
}
|
||||
|
||||
if ((u.field_set & (1<<UF_PATH)) != 0)
|
||||
{
|
||||
path_ = String (
|
||||
buf + u.field_data [UF_PATH].off,
|
||||
u.field_data [UF_PATH].len);
|
||||
}
|
||||
|
||||
if ((u.field_set & (1<<UF_QUERY)) != 0)
|
||||
{
|
||||
query_ = String (
|
||||
buf + u.field_data [UF_QUERY].off,
|
||||
u.field_data [UF_QUERY].len);
|
||||
}
|
||||
|
||||
if ((u.field_set & (1<<UF_FRAGMENT)) != 0)
|
||||
{
|
||||
fragment_ = String (
|
||||
buf + u.field_data [UF_FRAGMENT].off,
|
||||
u.field_data [UF_FRAGMENT].len);
|
||||
}
|
||||
|
||||
if ((u.field_set & (1<<UF_USERINFO)) != 0)
|
||||
{
|
||||
userinfo_ = String (
|
||||
buf + u.field_data [UF_USERINFO].off,
|
||||
u.field_data [UF_USERINFO].len);
|
||||
}
|
||||
|
||||
m_url = UniformResourceLocator (
|
||||
scheme_,
|
||||
host_,
|
||||
port_,
|
||||
port_string_,
|
||||
path_,
|
||||
query_,
|
||||
fragment_,
|
||||
userinfo_);
|
||||
}
|
||||
}
|
||||
|
||||
ParsedURL::ParsedURL (int error, UniformResourceLocator const& url)
|
||||
: m_error (error)
|
||||
, m_url (url)
|
||||
{
|
||||
}
|
||||
|
||||
ParsedURL::ParsedURL (ParsedURL const& other)
|
||||
: m_error (other.m_error)
|
||||
, m_url (other.m_url)
|
||||
{
|
||||
}
|
||||
|
||||
ParsedURL& ParsedURL::operator= (ParsedURL const& other)
|
||||
{
|
||||
m_error = other.m_error;
|
||||
m_url = other.m_url;
|
||||
return *this;
|
||||
}
|
||||
|
||||
int ParsedURL::error () const
|
||||
{
|
||||
return m_error;
|
||||
}
|
||||
|
||||
UniformResourceLocator ParsedURL::url () const
|
||||
{
|
||||
return m_url;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class ParsedURLTests : public UnitTest
|
||||
{
|
||||
public:
|
||||
void checkURL (String const& url)
|
||||
{
|
||||
ParsedURL result (url);
|
||||
expect (result.error () == 0);
|
||||
expect (result.url ().full () == url);
|
||||
}
|
||||
|
||||
void testURL ()
|
||||
{
|
||||
beginTestCase ("parse URL");
|
||||
|
||||
checkURL ("http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference.html");
|
||||
}
|
||||
|
||||
void runTest ()
|
||||
{
|
||||
testURL ();
|
||||
}
|
||||
|
||||
ParsedURLTests () : UnitTest ("ParsedURL", "beast", runManual)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
static ParsedURLTests parsedURLTests;
|
||||
123
modules/beast_asio/http/UniformResourceLocator.h
Normal file
123
modules/beast_asio/http/UniformResourceLocator.h
Normal file
@@ -0,0 +1,123 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_PROTOCOL_UNIFORMRESOURCELOCATOR_H_INCLUDED
|
||||
#define BEAST_ASIO_PROTOCOL_UNIFORMRESOURCELOCATOR_H_INCLUDED
|
||||
|
||||
/** A URL.
|
||||
The accompanying robust parser is hardened against all forms of attack.
|
||||
*/
|
||||
class UniformResourceLocator
|
||||
{
|
||||
public:
|
||||
/** Construct an empty URL. */
|
||||
explicit UniformResourceLocator ();
|
||||
|
||||
/** Construct a URL from it's components. */
|
||||
UniformResourceLocator (
|
||||
String schema_,
|
||||
String host_,
|
||||
uint16 port_,
|
||||
String port_string_,
|
||||
String path_,
|
||||
String query_ = "",
|
||||
String fragment_ = "",
|
||||
String userinfo_ = "");
|
||||
|
||||
/** Copy construct a URL. */
|
||||
UniformResourceLocator (UniformResourceLocator const& other);
|
||||
|
||||
/** Copy assign a URL. */
|
||||
UniformResourceLocator& operator= (UniformResourceLocator const& other);
|
||||
|
||||
/** Returns the scheme of the URL.
|
||||
If no scheme was specified, the string will be empty.
|
||||
*/
|
||||
String scheme () const;
|
||||
|
||||
/** Returns the host of the URL.
|
||||
If no host was specified, the string will be empty.
|
||||
*/
|
||||
String host () const;
|
||||
|
||||
/** Returns the port number as an integer.
|
||||
If no port was specified, the value will be zero.
|
||||
*/
|
||||
uint16 port () const;
|
||||
|
||||
/** Returns the port number as a string.
|
||||
If no port was specified, the string will be empty.
|
||||
*/
|
||||
String port_string () const;
|
||||
|
||||
/** Returns the path of the URL.
|
||||
If no path was specified, the string will be empty.
|
||||
*/
|
||||
String path () const;
|
||||
|
||||
/** Returns the query parameters portion of the URL.
|
||||
If no query parameters were present, the string will be empty.
|
||||
*/
|
||||
String query () const;
|
||||
|
||||
/** Returns the URL fragment, if any. */
|
||||
String fragment () const;
|
||||
|
||||
/** Returns the user information, if any. */
|
||||
String userinfo () const;
|
||||
|
||||
/** Retrieve the full URL as a single string. */
|
||||
String full () const;
|
||||
|
||||
private:
|
||||
String m_scheme;
|
||||
String m_host;
|
||||
uint16 m_port;
|
||||
String m_port_string;
|
||||
String m_path;
|
||||
String m_query;
|
||||
String m_fragment;
|
||||
String m_userinfo;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Parses a String containing a URL.
|
||||
*/
|
||||
class ParsedURL
|
||||
{
|
||||
public:
|
||||
ParsedURL ();
|
||||
explicit ParsedURL (String const& url);
|
||||
ParsedURL (int error, UniformResourceLocator const& url);
|
||||
ParsedURL (ParsedURL const& other);
|
||||
ParsedURL& operator= (ParsedURL const& other);
|
||||
|
||||
/** Zero for success, else a non zero value indicating failure. */
|
||||
int error () const;
|
||||
|
||||
/** The parsed URL if there was no error. */
|
||||
UniformResourceLocator url () const;
|
||||
|
||||
private:
|
||||
int m_error;
|
||||
UniformResourceLocator m_url;
|
||||
};
|
||||
|
||||
#endif
|
||||
14
modules/beast_asio/parsehttp/.gitignore
vendored
Normal file
14
modules/beast_asio/parsehttp/.gitignore
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
/out/
|
||||
core
|
||||
tags
|
||||
*.o
|
||||
test
|
||||
test_g
|
||||
test_fast
|
||||
url_parser
|
||||
parsertrace
|
||||
parsertrace_g
|
||||
*.mk
|
||||
*.Makefile
|
||||
*.so.*
|
||||
*.a
|
||||
7
modules/beast_asio/parsehttp/.mailmap
Normal file
7
modules/beast_asio/parsehttp/.mailmap
Normal file
@@ -0,0 +1,7 @@
|
||||
# update AUTHORS with:
|
||||
# git log --all --reverse --format='%aN <%aE>' | perl -ne 'BEGIN{print "# Authors ordered by first contribution.\n"} print unless $h{$_}; $h{$_} = 1' > AUTHORS
|
||||
Ryan Dahl <ry@tinyclouds.org>
|
||||
Salman Haq <salman.haq@asti-usa.com>
|
||||
Simon Zimmermann <simonz05@gmail.com>
|
||||
Thomas LE ROUX <thomas@november-eleven.fr> LE ROUX Thomas <thomas@procheo.fr>
|
||||
Thomas LE ROUX <thomas@november-eleven.fr> Thomas LE ROUX <thomas@procheo.fr>
|
||||
13
modules/beast_asio/parsehttp/.travis.yml
Normal file
13
modules/beast_asio/parsehttp/.travis.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
language: c
|
||||
|
||||
compiler:
|
||||
- clang
|
||||
- gcc
|
||||
|
||||
script:
|
||||
- "make"
|
||||
|
||||
notifications:
|
||||
email: false
|
||||
irc:
|
||||
- "irc.freenode.net#libuv"
|
||||
41
modules/beast_asio/parsehttp/AUTHORS
Normal file
41
modules/beast_asio/parsehttp/AUTHORS
Normal file
@@ -0,0 +1,41 @@
|
||||
# Authors ordered by first contribution.
|
||||
Ryan Dahl <ry@tinyclouds.org>
|
||||
Jeremy Hinegardner <jeremy@hinegardner.org>
|
||||
Sergey Shepelev <temotor@gmail.com>
|
||||
Joe Damato <ice799@gmail.com>
|
||||
tomika <tomika_nospam@freemail.hu>
|
||||
Phoenix Sol <phoenix@burninglabs.com>
|
||||
Cliff Frey <cliff@meraki.com>
|
||||
Ewen Cheslack-Postava <ewencp@cs.stanford.edu>
|
||||
Santiago Gala <sgala@apache.org>
|
||||
Tim Becker <tim.becker@syngenio.de>
|
||||
Jeff Terrace <jterrace@gmail.com>
|
||||
Ben Noordhuis <info@bnoordhuis.nl>
|
||||
Nathan Rajlich <nathan@tootallnate.net>
|
||||
Mark Nottingham <mnot@mnot.net>
|
||||
Aman Gupta <aman@tmm1.net>
|
||||
Tim Becker <tim.becker@kuriositaet.de>
|
||||
Sean Cunningham <sean.cunningham@mandiant.com>
|
||||
Peter Griess <pg@std.in>
|
||||
Salman Haq <salman.haq@asti-usa.com>
|
||||
Cliff Frey <clifffrey@gmail.com>
|
||||
Jon Kolb <jon@b0g.us>
|
||||
Fouad Mardini <f.mardini@gmail.com>
|
||||
Paul Querna <pquerna@apache.org>
|
||||
Felix Geisendörfer <felix@debuggable.com>
|
||||
koichik <koichik@improvement.jp>
|
||||
Andre Caron <andre.l.caron@gmail.com>
|
||||
Ivo Raisr <ivosh@ivosh.net>
|
||||
James McLaughlin <jamie@lacewing-project.org>
|
||||
David Gwynne <loki@animata.net>
|
||||
Thomas LE ROUX <thomas@november-eleven.fr>
|
||||
Randy Rizun <rrizun@ortivawireless.com>
|
||||
Andre Louis Caron <andre.louis.caron@usherbrooke.ca>
|
||||
Simon Zimmermann <simonz05@gmail.com>
|
||||
Erik Dubbelboer <erik@dubbelboer.com>
|
||||
Martell Malone <martellmalone@gmail.com>
|
||||
Bertrand Paquet <bpaquet@octo.com>
|
||||
BogDan Vatra <bogdan@kde.org>
|
||||
Peter Faiman <peter@thepicard.org>
|
||||
Corey Richardson <corey@octayn.net>
|
||||
Tóth Tamás <tomika_nospam@freemail.hu>
|
||||
4
modules/beast_asio/parsehttp/CONTRIBUTIONS
Normal file
4
modules/beast_asio/parsehttp/CONTRIBUTIONS
Normal file
@@ -0,0 +1,4 @@
|
||||
Contributors must agree to the Contributor License Agreement before patches
|
||||
can be accepted.
|
||||
|
||||
http://spreadsheets2.google.com/viewform?hl=en&formkey=dDJXOGUwbzlYaWM4cHN1MERwQS1CSnc6MQ
|
||||
23
modules/beast_asio/parsehttp/LICENSE-MIT
Normal file
23
modules/beast_asio/parsehttp/LICENSE-MIT
Normal file
@@ -0,0 +1,23 @@
|
||||
http_parser.c is based on src/http/ngx_http_parse.c from NGINX copyright
|
||||
Igor Sysoev.
|
||||
|
||||
Additional changes are licensed under the same terms as NGINX and
|
||||
copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
|
||||
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.
|
||||
105
modules/beast_asio/parsehttp/Makefile
Normal file
105
modules/beast_asio/parsehttp/Makefile
Normal file
@@ -0,0 +1,105 @@
|
||||
# Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
PLATFORM ?= $(shell sh -c 'uname -s | tr "[A-Z]" "[a-z]"')
|
||||
SONAME ?= libhttp_parser.so.2.1
|
||||
|
||||
CC?=gcc
|
||||
AR?=ar
|
||||
|
||||
CPPFLAGS += -I.
|
||||
CPPFLAGS_DEBUG = $(CPPFLAGS) -DHTTP_PARSER_STRICT=1
|
||||
CPPFLAGS_DEBUG += $(CPPFLAGS_DEBUG_EXTRA)
|
||||
CPPFLAGS_FAST = $(CPPFLAGS) -DHTTP_PARSER_STRICT=0
|
||||
CPPFLAGS_FAST += $(CPPFLAGS_FAST_EXTRA)
|
||||
|
||||
CFLAGS += -Wall -Wextra -Werror
|
||||
CFLAGS_DEBUG = $(CFLAGS) -O0 -g $(CFLAGS_DEBUG_EXTRA)
|
||||
CFLAGS_FAST = $(CFLAGS) -O3 $(CFLAGS_FAST_EXTRA)
|
||||
CFLAGS_LIB = $(CFLAGS_FAST) -fPIC
|
||||
|
||||
LDFLAGS_LIB = $(LDFLAGS) -shared
|
||||
|
||||
ifneq (darwin,$(PLATFORM))
|
||||
# TODO(bnoordhuis) The native SunOS linker expects -h rather than -soname...
|
||||
LDFLAGS_LIB += -Wl,-soname=$(SONAME)
|
||||
endif
|
||||
|
||||
test: test_g test_fast
|
||||
./test_g
|
||||
./test_fast
|
||||
|
||||
test_g: http_parser_g.o test_g.o
|
||||
$(CC) $(CFLAGS_DEBUG) $(LDFLAGS) http_parser_g.o test_g.o -o $@
|
||||
|
||||
test_g.o: test.c http_parser.h Makefile
|
||||
$(CC) $(CPPFLAGS_DEBUG) $(CFLAGS_DEBUG) -c test.c -o $@
|
||||
|
||||
http_parser_g.o: http_parser.c http_parser.h Makefile
|
||||
$(CC) $(CPPFLAGS_DEBUG) $(CFLAGS_DEBUG) -c http_parser.c -o $@
|
||||
|
||||
test_fast: http_parser.o test.o http_parser.h
|
||||
$(CC) $(CFLAGS_FAST) $(LDFLAGS) http_parser.o test.o -o $@
|
||||
|
||||
test.o: test.c http_parser.h Makefile
|
||||
$(CC) $(CPPFLAGS_FAST) $(CFLAGS_FAST) -c test.c -o $@
|
||||
|
||||
http_parser.o: http_parser.c http_parser.h Makefile
|
||||
$(CC) $(CPPFLAGS_FAST) $(CFLAGS_FAST) -c http_parser.c
|
||||
|
||||
test-run-timed: test_fast
|
||||
while(true) do time ./test_fast > /dev/null; done
|
||||
|
||||
test-valgrind: test_g
|
||||
valgrind ./test_g
|
||||
|
||||
libhttp_parser.o: http_parser.c http_parser.h Makefile
|
||||
$(CC) $(CPPFLAGS_FAST) $(CFLAGS_LIB) -c http_parser.c -o libhttp_parser.o
|
||||
|
||||
library: libhttp_parser.o
|
||||
$(CC) $(LDFLAGS_LIB) -o $(SONAME) $<
|
||||
|
||||
package: http_parser.o
|
||||
$(AR) rcs libhttp_parser.a http_parser.o
|
||||
|
||||
url_parser: http_parser.o contrib/url_parser.c
|
||||
$(CC) $(CPPFLAGS_FAST) $(CFLAGS_FAST) $^ -o $@
|
||||
|
||||
url_parser_g: http_parser_g.o contrib/url_parser.c
|
||||
$(CC) $(CPPFLAGS_DEBUG) $(CFLAGS_DEBUG) $^ -o $@
|
||||
|
||||
parsertrace: http_parser.o contrib/parsertrace.c
|
||||
$(CC) $(CPPFLAGS_FAST) $(CFLAGS_FAST) $^ -o parsertrace
|
||||
|
||||
parsertrace_g: http_parser_g.o contrib/parsertrace.c
|
||||
$(CC) $(CPPFLAGS_DEBUG) $(CFLAGS_DEBUG) $^ -o parsertrace_g
|
||||
|
||||
tags: http_parser.c http_parser.h test.c
|
||||
ctags $^
|
||||
|
||||
clean:
|
||||
rm -f *.o *.a tags test test_fast test_g \
|
||||
http_parser.tar libhttp_parser.so.* \
|
||||
url_parser url_parser_g parsertrace parsertrace_g
|
||||
|
||||
contrib/url_parser.c: http_parser.h
|
||||
contrib/parsertrace.c: http_parser.h
|
||||
|
||||
.PHONY: clean package test-run test-run-timed test-valgrind
|
||||
180
modules/beast_asio/parsehttp/README.md
Normal file
180
modules/beast_asio/parsehttp/README.md
Normal file
@@ -0,0 +1,180 @@
|
||||
HTTP Parser
|
||||
===========
|
||||
|
||||
[](https://travis-ci.org/joyent/http-parser)
|
||||
|
||||
This is a parser for HTTP messages written in C. It parses both requests and
|
||||
responses. The parser is designed to be used in performance HTTP
|
||||
applications. It does not make any syscalls nor allocations, it does not
|
||||
buffer data, it can be interrupted at anytime. Depending on your
|
||||
architecture, it only requires about 40 bytes of data per message
|
||||
stream (in a web server that is per connection).
|
||||
|
||||
Features:
|
||||
|
||||
* No dependencies
|
||||
* Handles persistent streams (keep-alive).
|
||||
* Decodes chunked encoding.
|
||||
* Upgrade support
|
||||
* Defends against buffer overflow attacks.
|
||||
|
||||
The parser extracts the following information from HTTP messages:
|
||||
|
||||
* Header fields and values
|
||||
* Content-Length
|
||||
* Request method
|
||||
* Response status code
|
||||
* Transfer-Encoding
|
||||
* HTTP version
|
||||
* Request URL
|
||||
* Message body
|
||||
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
One `http_parser` object is used per TCP connection. Initialize the struct
|
||||
using `http_parser_init()` and set the callbacks. That might look something
|
||||
like this for a request parser:
|
||||
|
||||
http_parser_settings settings;
|
||||
settings.on_url = my_url_callback;
|
||||
settings.on_header_field = my_header_field_callback;
|
||||
/* ... */
|
||||
|
||||
http_parser *parser = malloc(sizeof(http_parser));
|
||||
http_parser_init(parser, HTTP_REQUEST);
|
||||
parser->data = my_socket;
|
||||
|
||||
When data is received on the socket execute the parser and check for errors.
|
||||
|
||||
size_t len = 80*1024, nparsed;
|
||||
char buf[len];
|
||||
ssize_t recved;
|
||||
|
||||
recved = recv(fd, buf, len, 0);
|
||||
|
||||
if (recved < 0) {
|
||||
/* Handle error. */
|
||||
}
|
||||
|
||||
/* Start up / continue the parser.
|
||||
* Note we pass recved==0 to signal that EOF has been recieved.
|
||||
*/
|
||||
nparsed = http_parser_execute(parser, &settings, buf, recved);
|
||||
|
||||
if (parser->upgrade) {
|
||||
/* handle new protocol */
|
||||
} else if (nparsed != recved) {
|
||||
/* Handle error. Usually just close the connection. */
|
||||
}
|
||||
|
||||
HTTP needs to know where the end of the stream is. For example, sometimes
|
||||
servers send responses without Content-Length and expect the client to
|
||||
consume input (for the body) until EOF. To tell http_parser about EOF, give
|
||||
`0` as the forth parameter to `http_parser_execute()`. Callbacks and errors
|
||||
can still be encountered during an EOF, so one must still be prepared
|
||||
to receive them.
|
||||
|
||||
Scalar valued message information such as `status_code`, `method`, and the
|
||||
HTTP version are stored in the parser structure. This data is only
|
||||
temporally stored in `http_parser` and gets reset on each new message. If
|
||||
this information is needed later, copy it out of the structure during the
|
||||
`headers_complete` callback.
|
||||
|
||||
The parser decodes the transfer-encoding for both requests and responses
|
||||
transparently. That is, a chunked encoding is decoded before being sent to
|
||||
the on_body callback.
|
||||
|
||||
|
||||
The Special Problem of Upgrade
|
||||
------------------------------
|
||||
|
||||
HTTP supports upgrading the connection to a different protocol. An
|
||||
increasingly common example of this is the Web Socket protocol which sends
|
||||
a request like
|
||||
|
||||
GET /demo HTTP/1.1
|
||||
Upgrade: WebSocket
|
||||
Connection: Upgrade
|
||||
Host: example.com
|
||||
Origin: http://example.com
|
||||
WebSocket-Protocol: sample
|
||||
|
||||
followed by non-HTTP data.
|
||||
|
||||
(See http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-75 for more
|
||||
information the Web Socket protocol.)
|
||||
|
||||
To support this, the parser will treat this as a normal HTTP message without a
|
||||
body. Issuing both on_headers_complete and on_message_complete callbacks. However
|
||||
http_parser_execute() will stop parsing at the end of the headers and return.
|
||||
|
||||
The user is expected to check if `parser->upgrade` has been set to 1 after
|
||||
`http_parser_execute()` returns. Non-HTTP data begins at the buffer supplied
|
||||
offset by the return value of `http_parser_execute()`.
|
||||
|
||||
|
||||
Callbacks
|
||||
---------
|
||||
|
||||
During the `http_parser_execute()` call, the callbacks set in
|
||||
`http_parser_settings` will be executed. The parser maintains state and
|
||||
never looks behind, so buffering the data is not necessary. If you need to
|
||||
save certain data for later usage, you can do that from the callbacks.
|
||||
|
||||
There are two types of callbacks:
|
||||
|
||||
* notification `typedef int (*http_cb) (http_parser*);`
|
||||
Callbacks: on_message_begin, on_headers_complete, on_message_complete.
|
||||
* data `typedef int (*http_data_cb) (http_parser*, const char *at, size_t length);`
|
||||
Callbacks: (requests only) on_uri,
|
||||
(common) on_header_field, on_header_value, on_body;
|
||||
|
||||
Callbacks must return 0 on success. Returning a non-zero value indicates
|
||||
error to the parser, making it exit immediately.
|
||||
|
||||
In case you parse HTTP message in chunks (i.e. `read()` request line
|
||||
from socket, parse, read half headers, parse, etc) your data callbacks
|
||||
may be called more than once. Http-parser guarantees that data pointer is only
|
||||
valid for the lifetime of callback. You can also `read()` into a heap allocated
|
||||
buffer to avoid copying memory around if this fits your application.
|
||||
|
||||
Reading headers may be a tricky task if you read/parse headers partially.
|
||||
Basically, you need to remember whether last header callback was field or value
|
||||
and apply following logic:
|
||||
|
||||
(on_header_field and on_header_value shortened to on_h_*)
|
||||
------------------------ ------------ --------------------------------------------
|
||||
| State (prev. callback) | Callback | Description/action |
|
||||
------------------------ ------------ --------------------------------------------
|
||||
| nothing (first call) | on_h_field | Allocate new buffer and copy callback data |
|
||||
| | | into it |
|
||||
------------------------ ------------ --------------------------------------------
|
||||
| value | on_h_field | New header started. |
|
||||
| | | Copy current name,value buffers to headers |
|
||||
| | | list and allocate new buffer for new name |
|
||||
------------------------ ------------ --------------------------------------------
|
||||
| field | on_h_field | Previous name continues. Reallocate name |
|
||||
| | | buffer and append callback data to it |
|
||||
------------------------ ------------ --------------------------------------------
|
||||
| field | on_h_value | Value for current header started. Allocate |
|
||||
| | | new buffer and copy callback data to it |
|
||||
------------------------ ------------ --------------------------------------------
|
||||
| value | on_h_value | Value continues. Reallocate value buffer |
|
||||
| | | and append callback data to it |
|
||||
------------------------ ------------ --------------------------------------------
|
||||
|
||||
|
||||
Parsing URLs
|
||||
------------
|
||||
|
||||
A simplistic zero-copy URL parser is provided as `http_parser_parse_url()`.
|
||||
Users of this library may wish to use it to parse URLs constructed from
|
||||
consecutive `on_url` callbacks.
|
||||
|
||||
See examples of reading in headers:
|
||||
|
||||
* [partial example](http://gist.github.com/155877) in C
|
||||
* [from http-parser tests](http://github.com/joyent/http-parser/blob/37a0ff8/test.c#L403) in C
|
||||
* [from Node library](http://github.com/joyent/node/blob/842eaf4/src/http.js#L284) in Javascript
|
||||
156
modules/beast_asio/parsehttp/contrib/parsertrace.c
Normal file
156
modules/beast_asio/parsehttp/contrib/parsertrace.c
Normal file
@@ -0,0 +1,156 @@
|
||||
/* Based on src/http/ngx_http_parse.c from NGINX copyright Igor Sysoev
|
||||
*
|
||||
* Additional changes are licensed under the same terms as NGINX and
|
||||
* copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Dump what the parser finds to stdout as it happen */
|
||||
|
||||
#include "http_parser.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
int on_message_begin(http_parser* _) {
|
||||
(void)_;
|
||||
printf("\n***MESSAGE BEGIN***\n\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int on_headers_complete(http_parser* _) {
|
||||
(void)_;
|
||||
printf("\n***HEADERS COMPLETE***\n\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int on_message_complete(http_parser* _) {
|
||||
(void)_;
|
||||
printf("\n***MESSAGE COMPLETE***\n\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int on_url(http_parser* _, const char* at, size_t length) {
|
||||
(void)_;
|
||||
printf("Url: %.*s\n", (int)length, at);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int on_header_field(http_parser* _, const char* at, size_t length) {
|
||||
(void)_;
|
||||
printf("Header field: %.*s\n", (int)length, at);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int on_header_value(http_parser* _, const char* at, size_t length) {
|
||||
(void)_;
|
||||
printf("Header value: %.*s\n", (int)length, at);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int on_body(http_parser* _, const char* at, size_t length) {
|
||||
(void)_;
|
||||
printf("Body: %.*s\n", (int)length, at);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void usage(const char* name) {
|
||||
fprintf(stderr,
|
||||
"Usage: %s $type $filename\n"
|
||||
" type: -x, where x is one of {r,b,q}\n"
|
||||
" parses file as a Response, reQuest, or Both\n",
|
||||
name);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
enum http_parser_type file_type;
|
||||
|
||||
if (argc != 3) {
|
||||
usage(argv[0]);
|
||||
}
|
||||
|
||||
char* type = argv[1];
|
||||
if (type[0] != '-') {
|
||||
usage(argv[0]);
|
||||
}
|
||||
|
||||
switch (type[1]) {
|
||||
/* in the case of "-", type[1] will be NUL */
|
||||
case 'r':
|
||||
file_type = HTTP_RESPONSE;
|
||||
break;
|
||||
case 'q':
|
||||
file_type = HTTP_REQUEST;
|
||||
break;
|
||||
case 'b':
|
||||
file_type = HTTP_BOTH;
|
||||
break;
|
||||
default:
|
||||
usage(argv[0]);
|
||||
}
|
||||
|
||||
char* filename = argv[2];
|
||||
FILE* file = fopen(filename, "r");
|
||||
if (file == NULL) {
|
||||
perror("fopen");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
fseek(file, 0, SEEK_END);
|
||||
long file_length = ftell(file);
|
||||
if (file_length == -1) {
|
||||
perror("ftell");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
fseek(file, 0, SEEK_SET);
|
||||
|
||||
char* data = malloc(file_length);
|
||||
if (fread(data, 1, file_length, file) != (size_t)file_length) {
|
||||
fprintf(stderr, "couldn't read entire file\n");
|
||||
free(data);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
http_parser_settings settings;
|
||||
memset(&settings, 0, sizeof(settings));
|
||||
settings.on_message_begin = on_message_begin;
|
||||
settings.on_url = on_url;
|
||||
settings.on_header_field = on_header_field;
|
||||
settings.on_header_value = on_header_value;
|
||||
settings.on_headers_complete = on_headers_complete;
|
||||
settings.on_body = on_body;
|
||||
settings.on_message_complete = on_message_complete;
|
||||
|
||||
http_parser parser;
|
||||
http_parser_init(&parser, file_type);
|
||||
size_t nparsed = http_parser_execute(&parser, &settings, data, file_length);
|
||||
free(data);
|
||||
|
||||
if (nparsed != (size_t)file_length) {
|
||||
fprintf(stderr,
|
||||
"Error: %s (%s)\n",
|
||||
http_errno_description(HTTP_PARSER_ERRNO(&parser)),
|
||||
http_errno_name(HTTP_PARSER_ERRNO(&parser)));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
44
modules/beast_asio/parsehttp/contrib/url_parser.c
Normal file
44
modules/beast_asio/parsehttp/contrib/url_parser.c
Normal file
@@ -0,0 +1,44 @@
|
||||
#include "http_parser.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
void
|
||||
dump_url (const char *url, const struct http_parser_url *u)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
printf("\tfield_set: 0x%x, port: %u\n", u->field_set, u->port);
|
||||
for (i = 0; i < UF_MAX; i++) {
|
||||
if ((u->field_set & (1 << i)) == 0) {
|
||||
printf("\tfield_data[%u]: unset\n", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
printf("\tfield_data[%u]: off: %u len: %u part: \"%.*s\n",
|
||||
i,
|
||||
u->field_data[i].off,
|
||||
u->field_data[i].len,
|
||||
u->field_data[i].len,
|
||||
url + u->field_data[i].off);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char ** argv) {
|
||||
if (argc != 3) {
|
||||
printf("Syntax : %s connect|get url\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
struct http_parser_url u;
|
||||
int len = strlen(argv[2]);
|
||||
int connect = strcmp("connect", argv[1]) == 0 ? 1 : 0;
|
||||
printf("Parsing %s, connect %d\n", argv[2], connect);
|
||||
|
||||
int result = http_parser_parse_url(argv[2], len, connect, &u);
|
||||
if (result != 0) {
|
||||
printf("Parse error : %d\n", result);
|
||||
return result;
|
||||
}
|
||||
printf("Parse ok, result : \n");
|
||||
dump_url(argv[2], &u);
|
||||
return 0;
|
||||
}
|
||||
2199
modules/beast_asio/parsehttp/http_parser.c
Normal file
2199
modules/beast_asio/parsehttp/http_parser.c
Normal file
File diff suppressed because it is too large
Load Diff
111
modules/beast_asio/parsehttp/http_parser.gyp
Normal file
111
modules/beast_asio/parsehttp/http_parser.gyp
Normal file
@@ -0,0 +1,111 @@
|
||||
# This file is used with the GYP meta build system.
|
||||
# http://code.google.com/p/gyp/
|
||||
# To build try this:
|
||||
# svn co http://gyp.googlecode.com/svn/trunk gyp
|
||||
# ./gyp/gyp -f make --depth=`pwd` http_parser.gyp
|
||||
# ./out/Debug/test
|
||||
{
|
||||
'target_defaults': {
|
||||
'default_configuration': 'Debug',
|
||||
'configurations': {
|
||||
# TODO: hoist these out and put them somewhere common, because
|
||||
# RuntimeLibrary MUST MATCH across the entire project
|
||||
'Debug': {
|
||||
'defines': [ 'DEBUG', '_DEBUG' ],
|
||||
'cflags': [ '-Wall', '-Wextra', '-O0', '-g', '-ftrapv' ],
|
||||
'msvs_settings': {
|
||||
'VCCLCompilerTool': {
|
||||
'RuntimeLibrary': 1, # static debug
|
||||
},
|
||||
},
|
||||
},
|
||||
'Release': {
|
||||
'defines': [ 'NDEBUG' ],
|
||||
'cflags': [ '-Wall', '-Wextra', '-O3' ],
|
||||
'msvs_settings': {
|
||||
'VCCLCompilerTool': {
|
||||
'RuntimeLibrary': 0, # static release
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
'msvs_settings': {
|
||||
'VCCLCompilerTool': {
|
||||
},
|
||||
'VCLibrarianTool': {
|
||||
},
|
||||
'VCLinkerTool': {
|
||||
'GenerateDebugInformation': 'true',
|
||||
},
|
||||
},
|
||||
'conditions': [
|
||||
['OS == "win"', {
|
||||
'defines': [
|
||||
'WIN32'
|
||||
],
|
||||
}]
|
||||
],
|
||||
},
|
||||
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'http_parser',
|
||||
'type': 'static_library',
|
||||
'include_dirs': [ '.' ],
|
||||
'direct_dependent_settings': {
|
||||
'defines': [ 'HTTP_PARSER_STRICT=0' ],
|
||||
'include_dirs': [ '.' ],
|
||||
},
|
||||
'defines': [ 'HTTP_PARSER_STRICT=0' ],
|
||||
'sources': [ './http_parser.c', ],
|
||||
'conditions': [
|
||||
['OS=="win"', {
|
||||
'msvs_settings': {
|
||||
'VCCLCompilerTool': {
|
||||
# Compile as C++. http_parser.c is actually C99, but C++ is
|
||||
# close enough in this case.
|
||||
'CompileAs': 2,
|
||||
},
|
||||
},
|
||||
}]
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
'target_name': 'http_parser_strict',
|
||||
'type': 'static_library',
|
||||
'include_dirs': [ '.' ],
|
||||
'direct_dependent_settings': {
|
||||
'defines': [ 'HTTP_PARSER_STRICT=1' ],
|
||||
'include_dirs': [ '.' ],
|
||||
},
|
||||
'defines': [ 'HTTP_PARSER_STRICT=1' ],
|
||||
'sources': [ './http_parser.c', ],
|
||||
'conditions': [
|
||||
['OS=="win"', {
|
||||
'msvs_settings': {
|
||||
'VCCLCompilerTool': {
|
||||
# Compile as C++. http_parser.c is actually C99, but C++ is
|
||||
# close enough in this case.
|
||||
'CompileAs': 2,
|
||||
},
|
||||
},
|
||||
}]
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
'target_name': 'test-nonstrict',
|
||||
'type': 'executable',
|
||||
'dependencies': [ 'http_parser' ],
|
||||
'sources': [ 'test.c' ]
|
||||
},
|
||||
|
||||
{
|
||||
'target_name': 'test-strict',
|
||||
'type': 'executable',
|
||||
'dependencies': [ 'http_parser_strict' ],
|
||||
'sources': [ 'test.c' ]
|
||||
}
|
||||
]
|
||||
}
|
||||
318
modules/beast_asio/parsehttp/http_parser.h
Normal file
318
modules/beast_asio/parsehttp/http_parser.h
Normal file
@@ -0,0 +1,318 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* 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 http_parser_h
|
||||
#define http_parser_h
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Also update SONAME in the Makefile whenever you change these. */
|
||||
#define HTTP_PARSER_VERSION_MAJOR 2
|
||||
#define HTTP_PARSER_VERSION_MINOR 1
|
||||
#define HTTP_PARSER_VERSION_PATCH 0
|
||||
|
||||
#include <sys/types.h>
|
||||
#if defined(_WIN32) && !defined(__MINGW32__) && (!defined(_MSC_VER) || _MSC_VER<1600)
|
||||
#include <BaseTsd.h>
|
||||
#include <stddef.h>
|
||||
typedef __int8 int8_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef __int16 int16_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef __int32 int32_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
/* Compile with -DHTTP_PARSER_STRICT=0 to make less checks, but run
|
||||
* faster
|
||||
*/
|
||||
#ifndef HTTP_PARSER_STRICT
|
||||
# define HTTP_PARSER_STRICT 1
|
||||
#endif
|
||||
|
||||
/* Maximium header size allowed */
|
||||
#define HTTP_MAX_HEADER_SIZE (80*1024)
|
||||
|
||||
|
||||
typedef struct http_parser http_parser;
|
||||
typedef struct http_parser_settings http_parser_settings;
|
||||
|
||||
|
||||
/* Callbacks should return non-zero to indicate an error. The parser will
|
||||
* then halt execution.
|
||||
*
|
||||
* The one exception is on_headers_complete. In a HTTP_RESPONSE parser
|
||||
* returning '1' from on_headers_complete will tell the parser that it
|
||||
* should not expect a body. This is used when receiving a response to a
|
||||
* HEAD request which may contain 'Content-Length' or 'Transfer-Encoding:
|
||||
* chunked' headers that indicate the presence of a body.
|
||||
*
|
||||
* http_data_cb does not return data chunks. It will be call arbitrarally
|
||||
* many times for each string. E.G. you might get 10 callbacks for "on_url"
|
||||
* each providing just a few characters more data.
|
||||
*/
|
||||
typedef int (*http_data_cb) (http_parser*, const char *at, size_t length);
|
||||
typedef int (*http_cb) (http_parser*);
|
||||
|
||||
|
||||
/* Request Methods */
|
||||
#define HTTP_METHOD_MAP(XX) \
|
||||
XX(0, DELETE, DELETE) \
|
||||
XX(1, GET, GET) \
|
||||
XX(2, HEAD, HEAD) \
|
||||
XX(3, POST, POST) \
|
||||
XX(4, PUT, PUT) \
|
||||
/* pathological */ \
|
||||
XX(5, CONNECT, CONNECT) \
|
||||
XX(6, OPTIONS, OPTIONS) \
|
||||
XX(7, TRACE, TRACE) \
|
||||
/* webdav */ \
|
||||
XX(8, COPY, COPY) \
|
||||
XX(9, LOCK, LOCK) \
|
||||
XX(10, MKCOL, MKCOL) \
|
||||
XX(11, MOVE, MOVE) \
|
||||
XX(12, PROPFIND, PROPFIND) \
|
||||
XX(13, PROPPATCH, PROPPATCH) \
|
||||
XX(14, SEARCH, SEARCH) \
|
||||
XX(15, UNLOCK, UNLOCK) \
|
||||
/* subversion */ \
|
||||
XX(16, REPORT, REPORT) \
|
||||
XX(17, MKACTIVITY, MKACTIVITY) \
|
||||
XX(18, CHECKOUT, CHECKOUT) \
|
||||
XX(19, MERGE, MERGE) \
|
||||
/* upnp */ \
|
||||
XX(20, MSEARCH, M-SEARCH) \
|
||||
XX(21, NOTIFY, NOTIFY) \
|
||||
XX(22, SUBSCRIBE, SUBSCRIBE) \
|
||||
XX(23, UNSUBSCRIBE, UNSUBSCRIBE) \
|
||||
/* RFC-5789 */ \
|
||||
XX(24, PATCH, PATCH) \
|
||||
XX(25, PURGE, PURGE) \
|
||||
|
||||
enum http_method
|
||||
{
|
||||
#define XX(num, name, string) HTTP_##name = num,
|
||||
HTTP_METHOD_MAP(XX)
|
||||
#undef XX
|
||||
};
|
||||
|
||||
|
||||
enum http_parser_type { HTTP_REQUEST, HTTP_RESPONSE, HTTP_BOTH };
|
||||
|
||||
|
||||
/* Flag values for http_parser.flags field */
|
||||
enum flags
|
||||
{ F_CHUNKED = 1 << 0
|
||||
, F_CONNECTION_KEEP_ALIVE = 1 << 1
|
||||
, F_CONNECTION_CLOSE = 1 << 2
|
||||
, F_TRAILING = 1 << 3
|
||||
, F_UPGRADE = 1 << 4
|
||||
, F_SKIPBODY = 1 << 5
|
||||
};
|
||||
|
||||
|
||||
/* Map for errno-related constants
|
||||
*
|
||||
* The provided argument should be a macro that takes 2 arguments.
|
||||
*/
|
||||
#define HTTP_ERRNO_MAP(XX) \
|
||||
/* No error */ \
|
||||
XX(OK, "success") \
|
||||
\
|
||||
/* Callback-related errors */ \
|
||||
XX(CB_message_begin, "the on_message_begin callback failed") \
|
||||
XX(CB_status_complete, "the on_status_complete callback failed") \
|
||||
XX(CB_url, "the on_url callback failed") \
|
||||
XX(CB_header_field, "the on_header_field callback failed") \
|
||||
XX(CB_header_value, "the on_header_value callback failed") \
|
||||
XX(CB_headers_complete, "the on_headers_complete callback failed") \
|
||||
XX(CB_body, "the on_body callback failed") \
|
||||
XX(CB_message_complete, "the on_message_complete callback failed") \
|
||||
\
|
||||
/* Parsing-related errors */ \
|
||||
XX(INVALID_EOF_STATE, "stream ended at an unexpected time") \
|
||||
XX(HEADER_OVERFLOW, \
|
||||
"too many header bytes seen; overflow detected") \
|
||||
XX(CLOSED_CONNECTION, \
|
||||
"data received after completed connection: close message") \
|
||||
XX(INVALID_VERSION, "invalid HTTP version") \
|
||||
XX(INVALID_STATUS, "invalid HTTP status code") \
|
||||
XX(INVALID_METHOD, "invalid HTTP method") \
|
||||
XX(INVALID_URL, "invalid URL") \
|
||||
XX(INVALID_HOST, "invalid host") \
|
||||
XX(INVALID_PORT, "invalid port") \
|
||||
XX(INVALID_PATH, "invalid path") \
|
||||
XX(INVALID_QUERY_STRING, "invalid query string") \
|
||||
XX(INVALID_FRAGMENT, "invalid fragment") \
|
||||
XX(LF_EXPECTED, "LF character expected") \
|
||||
XX(INVALID_HEADER_TOKEN, "invalid character in header") \
|
||||
XX(INVALID_CONTENT_LENGTH, \
|
||||
"invalid character in content-length header") \
|
||||
XX(INVALID_CHUNK_SIZE, \
|
||||
"invalid character in chunk size header") \
|
||||
XX(INVALID_CONSTANT, "invalid constant string") \
|
||||
XX(INVALID_INTERNAL_STATE, "encountered unexpected internal state")\
|
||||
XX(STRICT, "strict mode assertion failed") \
|
||||
XX(PAUSED, "parser is paused") \
|
||||
XX(UNKNOWN, "an unknown error occurred")
|
||||
|
||||
|
||||
/* Define HPE_* values for each errno value above */
|
||||
#define HTTP_ERRNO_GEN(n, s) HPE_##n,
|
||||
enum http_errno {
|
||||
HTTP_ERRNO_MAP(HTTP_ERRNO_GEN)
|
||||
};
|
||||
#undef HTTP_ERRNO_GEN
|
||||
|
||||
|
||||
/* Get an http_errno value from an http_parser */
|
||||
#define HTTP_PARSER_ERRNO(p) ((enum http_errno) (p)->http_errno)
|
||||
|
||||
|
||||
struct http_parser {
|
||||
/** PRIVATE **/
|
||||
unsigned char type : 2; /* enum http_parser_type */
|
||||
unsigned char flags : 6; /* F_* values from 'flags' enum; semi-public */
|
||||
unsigned char state; /* enum state from http_parser.c */
|
||||
unsigned char header_state; /* enum header_state from http_parser.c */
|
||||
unsigned char index; /* index into current matcher */
|
||||
|
||||
uint32_t nread; /* # bytes read in various scenarios */
|
||||
uint64_t content_length; /* # bytes in body (0 if no Content-Length header) */
|
||||
|
||||
/** READ-ONLY **/
|
||||
unsigned short http_major;
|
||||
unsigned short http_minor;
|
||||
unsigned short status_code; /* responses only */
|
||||
unsigned char method; /* requests only */
|
||||
unsigned char http_errno : 7;
|
||||
|
||||
/* 1 = Upgrade header was present and the parser has exited because of that.
|
||||
* 0 = No upgrade header present.
|
||||
* Should be checked when http_parser_execute() returns in addition to
|
||||
* error checking.
|
||||
*/
|
||||
unsigned char upgrade : 1;
|
||||
|
||||
/** PUBLIC **/
|
||||
void *data; /* A pointer to get hook to the "connection" or "socket" object */
|
||||
};
|
||||
|
||||
|
||||
struct http_parser_settings {
|
||||
http_cb on_message_begin;
|
||||
http_data_cb on_url;
|
||||
http_cb on_status_complete;
|
||||
http_data_cb on_header_field;
|
||||
http_data_cb on_header_value;
|
||||
http_cb on_headers_complete;
|
||||
http_data_cb on_body;
|
||||
http_cb on_message_complete;
|
||||
};
|
||||
|
||||
|
||||
enum http_parser_url_fields
|
||||
{ UF_SCHEMA = 0
|
||||
, UF_HOST = 1
|
||||
, UF_PORT = 2
|
||||
, UF_PATH = 3
|
||||
, UF_QUERY = 4
|
||||
, UF_FRAGMENT = 5
|
||||
, UF_USERINFO = 6
|
||||
, UF_MAX = 7
|
||||
};
|
||||
|
||||
|
||||
/* Result structure for http_parser_parse_url().
|
||||
*
|
||||
* Callers should index into field_data[] with UF_* values iff field_set
|
||||
* has the relevant (1 << UF_*) bit set. As a courtesy to clients (and
|
||||
* because we probably have padding left over), we convert any port to
|
||||
* a uint16_t.
|
||||
*/
|
||||
struct http_parser_url {
|
||||
uint16_t field_set; /* Bitmask of (1 << UF_*) values */
|
||||
uint16_t port; /* Converted UF_PORT string */
|
||||
|
||||
struct {
|
||||
uint16_t off; /* Offset into buffer in which field starts */
|
||||
uint16_t len; /* Length of run in buffer */
|
||||
} field_data[UF_MAX];
|
||||
};
|
||||
|
||||
|
||||
/* Returns the library version. Bits 16-23 contain the major version number,
|
||||
* bits 8-15 the minor version number and bits 0-7 the patch level.
|
||||
* Usage example:
|
||||
*
|
||||
* unsigned long version = http_parser_version();
|
||||
* unsigned major = (version >> 16) & 255;
|
||||
* unsigned minor = (version >> 8) & 255;
|
||||
* unsigned patch = version & 255;
|
||||
* printf("http_parser v%u.%u.%u\n", major, minor, version);
|
||||
*/
|
||||
unsigned long http_parser_version(void);
|
||||
|
||||
void http_parser_init(http_parser *parser, enum http_parser_type type);
|
||||
|
||||
|
||||
size_t http_parser_execute(http_parser *parser,
|
||||
const http_parser_settings *settings,
|
||||
const char *data,
|
||||
size_t len);
|
||||
|
||||
|
||||
/* If http_should_keep_alive() in the on_headers_complete or
|
||||
* on_message_complete callback returns 0, then this should be
|
||||
* the last message on the connection.
|
||||
* If you are the server, respond with the "Connection: close" header.
|
||||
* If you are the client, close the connection.
|
||||
*/
|
||||
int http_should_keep_alive(const http_parser *parser);
|
||||
|
||||
/* Returns a string version of the HTTP method. */
|
||||
const char *http_method_str(enum http_method m);
|
||||
|
||||
/* Return a string name of the given error */
|
||||
const char *http_errno_name(enum http_errno err);
|
||||
|
||||
/* Return a string description of the given error */
|
||||
const char *http_errno_description(enum http_errno err);
|
||||
|
||||
/* Parse a URL; return nonzero on failure */
|
||||
int http_parser_parse_url(const char *buf, size_t buflen,
|
||||
int is_connect,
|
||||
struct http_parser_url *u);
|
||||
|
||||
/* Pause or un-pause the parser; a nonzero value pauses */
|
||||
void http_parser_pause(http_parser *parser, int paused);
|
||||
|
||||
/* Checks if this is the final chunk of the body. */
|
||||
int http_body_is_final(const http_parser *parser);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
3439
modules/beast_asio/parsehttp/test.c
Normal file
3439
modules/beast_asio/parsehttp/test.c
Normal file
File diff suppressed because it is too large
Load Diff
141
modules/beast_asio/protocol/HandshakeDetectLogic.h
Normal file
141
modules/beast_asio/protocol/HandshakeDetectLogic.h
Normal file
@@ -0,0 +1,141 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_HANDSHAKE_HANDSHAKEDETECTLOGIC_H_INCLUDED
|
||||
#define BEAST_ASIO_HANDSHAKE_HANDSHAKEDETECTLOGIC_H_INCLUDED
|
||||
|
||||
class HandshakeDetectLogic
|
||||
{
|
||||
public:
|
||||
HandshakeDetectLogic ()
|
||||
: m_finished (false)
|
||||
, m_success (false)
|
||||
{
|
||||
}
|
||||
|
||||
/** How many bytes maximum we might need.
|
||||
|
||||
This is the largest number of bytes that the detector
|
||||
might need in order to come to a conclusion about
|
||||
whether or not the handshake is a match. Depending
|
||||
on the data, it could come to that conclusion sooner
|
||||
though.
|
||||
|
||||
Use read_some instead of read so that the detect logic
|
||||
can reject the handshake sooner if possible.
|
||||
*/
|
||||
virtual std::size_t max_needed () = 0;
|
||||
|
||||
/** How many bytes the handshake consumes.
|
||||
If the detector processes the entire handshake this will
|
||||
be non zero. The SSL detector would return 0, since we
|
||||
want all the existing bytes to be passed on.
|
||||
*/
|
||||
virtual std::size_t bytes_consumed () = 0;
|
||||
|
||||
/** Return true if we have enough data to form a conclusion.
|
||||
*/
|
||||
bool finished () const noexcept
|
||||
{
|
||||
return m_finished;
|
||||
}
|
||||
|
||||
/** Return true if we came to a conclusion and the data matched.
|
||||
*/
|
||||
bool success () const noexcept
|
||||
{
|
||||
return m_finished && m_success;
|
||||
}
|
||||
|
||||
protected:
|
||||
void conclude (bool success = true)
|
||||
{
|
||||
m_finished = true;
|
||||
m_success = success;
|
||||
}
|
||||
|
||||
void fail ()
|
||||
{
|
||||
conclude (false);
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_finished;
|
||||
bool m_success;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Wraps the logic and exports it as an abstract interface.
|
||||
*/
|
||||
template <typename Logic>
|
||||
class HandshakeDetectLogicType
|
||||
{
|
||||
public:
|
||||
typedef Logic LogicType;
|
||||
typedef typename Logic::arg_type arg_type;
|
||||
|
||||
explicit HandshakeDetectLogicType (arg_type const& arg = arg_type ())
|
||||
: m_logic (arg)
|
||||
{
|
||||
}
|
||||
|
||||
LogicType& get ()
|
||||
{
|
||||
return m_logic;
|
||||
}
|
||||
|
||||
std::size_t max_needed ()
|
||||
{
|
||||
return m_logic.max_needed ();
|
||||
}
|
||||
|
||||
std::size_t bytes_consumed ()
|
||||
{
|
||||
return m_logic.bytes_consumed ();
|
||||
}
|
||||
|
||||
bool finished ()
|
||||
{
|
||||
return m_logic.finished ();
|
||||
}
|
||||
|
||||
/** If finished is true, this tells us if the handshake was detected.
|
||||
*/
|
||||
bool success ()
|
||||
{
|
||||
return m_logic.success ();
|
||||
}
|
||||
|
||||
/** Analyze the buffer to match the Handshake.
|
||||
Returns `true` if the analysis is complete.
|
||||
*/
|
||||
template <typename ConstBufferSequence>
|
||||
bool analyze (ConstBufferSequence const& buffer)
|
||||
{
|
||||
bassert (! m_logic.finished ());
|
||||
m_logic.analyze (buffer);
|
||||
return m_logic.finished ();
|
||||
}
|
||||
|
||||
private:
|
||||
Logic m_logic;
|
||||
};
|
||||
|
||||
#endif
|
||||
20
modules/beast_asio/protocol/HandshakeDetectLogicPROXY.cpp
Normal file
20
modules/beast_asio/protocol/HandshakeDetectLogicPROXY.cpp
Normal file
@@ -0,0 +1,20 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
|
||||
159
modules/beast_asio/protocol/HandshakeDetectLogicPROXY.h
Normal file
159
modules/beast_asio/protocol/HandshakeDetectLogicPROXY.h
Normal file
@@ -0,0 +1,159 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_HANDSHAKE_HANDSHAKEDETECTLOGICPROXY_H_INCLUDED
|
||||
#define BEAST_ASIO_HANDSHAKE_HANDSHAKEDETECTLOGICPROXY_H_INCLUDED
|
||||
|
||||
/** Handshake detector for the PROXY protcol
|
||||
|
||||
http://haproxy.1wt.eu/download/1.5/doc/proxy-protocol.txt
|
||||
*/
|
||||
class HandshakeDetectLogicPROXY : public HandshakeDetectLogic
|
||||
{
|
||||
public:
|
||||
typedef int arg_type;
|
||||
|
||||
enum
|
||||
{
|
||||
// This is for version 1. The largest number of bytes
|
||||
// that we could possibly need to parse a valid handshake.
|
||||
// We will reject it much sooner if there's an illegal value.
|
||||
//
|
||||
maxBytesNeeded = 107 // including CRLF, no null term
|
||||
};
|
||||
|
||||
struct ProxyInfo
|
||||
{
|
||||
typedef InputParser::IPv4Address IPv4Address;
|
||||
|
||||
String protocol; // "TCP4", "TCP6", "UNKNOWN"
|
||||
|
||||
IPv4Address sourceAddress;
|
||||
IPv4Address destAddress;
|
||||
|
||||
uint16 sourcePort;
|
||||
uint16 destPort;
|
||||
};
|
||||
|
||||
explicit HandshakeDetectLogicPROXY (arg_type const&)
|
||||
: m_consumed (0)
|
||||
{
|
||||
}
|
||||
|
||||
ProxyInfo const& getInfo () const noexcept
|
||||
{
|
||||
return m_info;
|
||||
}
|
||||
|
||||
std::size_t max_needed ()
|
||||
{
|
||||
return maxBytesNeeded;
|
||||
}
|
||||
|
||||
std::size_t bytes_consumed ()
|
||||
{
|
||||
return m_consumed;
|
||||
}
|
||||
|
||||
template <typename ConstBufferSequence>
|
||||
void analyze (ConstBufferSequence const& buffer)
|
||||
{
|
||||
FixedInputBufferSize <maxBytesNeeded> in (buffer);
|
||||
|
||||
InputParser::State state;
|
||||
|
||||
analyze_input (in, state);
|
||||
|
||||
if (state.passed ())
|
||||
{
|
||||
m_consumed = in.used ();
|
||||
conclude (true);
|
||||
}
|
||||
else if (state.failed ())
|
||||
{
|
||||
conclude (false);
|
||||
}
|
||||
}
|
||||
|
||||
void analyze_input (FixedInputBuffer& in, InputParser::State& state)
|
||||
{
|
||||
using namespace InputParser;
|
||||
|
||||
if (! match (in, "PROXY ", state))
|
||||
return;
|
||||
|
||||
if (match (in, "TCP4 "))
|
||||
{
|
||||
m_info.protocol = "TCP4";
|
||||
|
||||
if (! read (in, m_info.sourceAddress, state))
|
||||
return;
|
||||
|
||||
if (! match (in, " ", state))
|
||||
return;
|
||||
|
||||
if (! read (in, m_info.destAddress, state))
|
||||
return;
|
||||
|
||||
if (! match (in, " ", state))
|
||||
return;
|
||||
|
||||
UInt16Str sourcePort;
|
||||
if (! read (in, sourcePort, state))
|
||||
return;
|
||||
m_info.sourcePort = sourcePort.value;
|
||||
|
||||
if (! match (in, " ", state))
|
||||
return;
|
||||
|
||||
UInt16Str destPort;
|
||||
if (! read (in, destPort, state))
|
||||
return;
|
||||
m_info.destPort = destPort.value;
|
||||
|
||||
if (! match (in, "\r\n", state))
|
||||
return;
|
||||
|
||||
state = State::pass;
|
||||
return;
|
||||
}
|
||||
else if (match (in, "TCP6 "))
|
||||
{
|
||||
m_info.protocol = "TCP6";
|
||||
|
||||
state = State::fail;
|
||||
return;
|
||||
}
|
||||
else if (match (in, "UNKNOWN "))
|
||||
{
|
||||
m_info.protocol = "UNKNOWN";
|
||||
|
||||
state = State::fail;
|
||||
return;
|
||||
}
|
||||
|
||||
state = State::fail;
|
||||
}
|
||||
|
||||
private:
|
||||
std::size_t m_consumed;
|
||||
ProxyInfo m_info;
|
||||
};
|
||||
|
||||
#endif
|
||||
108
modules/beast_asio/protocol/HandshakeDetectLogicSSL2.h
Normal file
108
modules/beast_asio/protocol/HandshakeDetectLogicSSL2.h
Normal file
@@ -0,0 +1,108 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_HANDSHAKE_HANDSHAKEDETECTLOGICSSL2_H_INCLUDED
|
||||
#define BEAST_ASIO_HANDSHAKE_HANDSHAKEDETECTLOGICSSL2_H_INCLUDED
|
||||
|
||||
// Handshake for SSL 2
|
||||
//
|
||||
// http://tools.ietf.org/html/rfc5246#appendix-E.2
|
||||
//
|
||||
// uint8 V2CipherSpec[3];
|
||||
// struct {
|
||||
// uint16 msg_length;
|
||||
// uint8 msg_type;
|
||||
// Version version; Should be 'ProtocolVersion'?
|
||||
// uint16 cipher_spec_length;
|
||||
// uint16 session_id_length;
|
||||
// uint16 challenge_length;
|
||||
// ...
|
||||
//
|
||||
class HandshakeDetectLogicSSL2 : public HandshakeDetectLogic
|
||||
{
|
||||
public:
|
||||
typedef int arg_type;
|
||||
|
||||
explicit HandshakeDetectLogicSSL2 (arg_type const&)
|
||||
{
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
bytesNeeded = 3
|
||||
};
|
||||
|
||||
std::size_t max_needed ()
|
||||
{
|
||||
return bytesNeeded;
|
||||
}
|
||||
|
||||
std::size_t bytes_consumed ()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename ConstBufferSequence>
|
||||
void analyze (ConstBufferSequence const& buffer)
|
||||
{
|
||||
FixedInputBufferSize <bytesNeeded> in (buffer);
|
||||
|
||||
{
|
||||
uint8 byte;
|
||||
if (! in.peek (&byte))
|
||||
return;
|
||||
|
||||
// First byte must have the high bit set
|
||||
//
|
||||
if((byte & 0x80) != 0x80)
|
||||
return fail ();
|
||||
}
|
||||
|
||||
// The remaining bits contain the
|
||||
// length of the following data in bytes.
|
||||
//
|
||||
uint16 msg_length;
|
||||
if (! in.readNetworkInteger(&msg_length))
|
||||
return;
|
||||
|
||||
// sizeof (msg_type +
|
||||
// Version (ProtcolVersion?) +
|
||||
// cipher_spec_length +
|
||||
// session_id_length +
|
||||
// challenge_length)
|
||||
//
|
||||
// Should be 9 or greater.
|
||||
//
|
||||
if (msg_length < 9)
|
||||
return fail ();
|
||||
|
||||
uint8 msg_type;
|
||||
if (! in.read (&msg_type))
|
||||
return;
|
||||
|
||||
// The msg_type must be 0x01 for a version 2 ClientHello
|
||||
//
|
||||
if (msg_type != 0x01)
|
||||
return fail ();
|
||||
|
||||
conclude ();
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
82
modules/beast_asio/protocol/HandshakeDetectLogicSSL3.h
Normal file
82
modules/beast_asio/protocol/HandshakeDetectLogicSSL3.h
Normal file
@@ -0,0 +1,82 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_HANDSHAKE_HANDSHAKEDETECTLOGICSSL3_H_INCLUDED
|
||||
#define BEAST_ASIO_HANDSHAKE_HANDSHAKEDETECTLOGICSSL3_H_INCLUDED
|
||||
|
||||
// Handshake for SSL 3 (Also TLS 1.0 and 1.1)
|
||||
//
|
||||
// http://www.ietf.org/rfc/rfc2246.txt
|
||||
//
|
||||
// Section 7.4. Handshake protocol
|
||||
//
|
||||
class HandshakeDetectLogicSSL3 : public HandshakeDetectLogic
|
||||
{
|
||||
public:
|
||||
typedef int arg_type; // dummy
|
||||
|
||||
explicit HandshakeDetectLogicSSL3 (arg_type const&)
|
||||
{
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
bytesNeeded = 6
|
||||
};
|
||||
|
||||
std::size_t max_needed ()
|
||||
{
|
||||
return bytesNeeded;
|
||||
}
|
||||
|
||||
std::size_t bytes_consumed ()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename ConstBufferSequence>
|
||||
void analyze (ConstBufferSequence const& buffer)
|
||||
{
|
||||
uint16 version;
|
||||
FixedInputBufferSize <bytesNeeded> in (buffer);
|
||||
|
||||
uint8 msg_type;
|
||||
if (! in.read (&msg_type))
|
||||
return;
|
||||
|
||||
// msg_type must be 0x16 = "SSL Handshake"
|
||||
//
|
||||
if (msg_type != 0x16)
|
||||
return fail ();
|
||||
|
||||
if (! in.read (&version))
|
||||
return;
|
||||
version = fromNetworkByteOrder (version);
|
||||
|
||||
uint16 length;
|
||||
if (! in.read (&length))
|
||||
return;
|
||||
|
||||
length = fromNetworkByteOrder (length);
|
||||
|
||||
conclude ();
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
206
modules/beast_asio/protocol/HandshakeDetector.h
Normal file
206
modules/beast_asio/protocol/HandshakeDetector.h
Normal file
@@ -0,0 +1,206 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_HANDSHAKE_HANDSHAKEDETECTOR_H_INCLUDED
|
||||
#define BEAST_ASIO_HANDSHAKE_HANDSHAKEDETECTOR_H_INCLUDED
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** A wrapper to decode the handshake data on a Stream.
|
||||
|
||||
Stream must meet these requirements
|
||||
|
||||
For detect:
|
||||
SyncReadStream
|
||||
|
||||
For async_detect:
|
||||
AsyncReadStream
|
||||
|
||||
Logic must meet this requirement:
|
||||
HandshakeDetectLogic
|
||||
*/
|
||||
template <typename Stream, typename Logic>
|
||||
class HandshakeDetectorType
|
||||
{
|
||||
protected:
|
||||
typedef boost::system::error_code error_code;
|
||||
|
||||
public:
|
||||
Logic& getLogic ()
|
||||
{
|
||||
return m_logic.get ();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/** Synchronous handshake detect.
|
||||
The bytes from the input sequence in the specified buffer
|
||||
are used first.
|
||||
*/
|
||||
template <typename Allocator>
|
||||
error_code detect (Stream& stream,
|
||||
boost::asio::basic_streambuf <Allocator>& buffer)
|
||||
{
|
||||
typedef boost::asio::basic_streambuf <Allocator> BuffersType;
|
||||
|
||||
error_code ec;
|
||||
|
||||
do
|
||||
{
|
||||
m_logic.analyze (buffer.data ());
|
||||
|
||||
if (m_logic.finished ())
|
||||
{
|
||||
// consume what we used (for SSL its 0)
|
||||
std::size_t const consumed = m_logic.bytes_consumed ();
|
||||
bassert (consumed <= buffer.size ());
|
||||
buffer.consume (consumed);
|
||||
break;
|
||||
}
|
||||
|
||||
std::size_t const available = buffer.size ();
|
||||
std::size_t const needed = m_logic.max_needed ();
|
||||
|
||||
// If postcondition fails, loop will never end
|
||||
if (meets_postcondition (available < needed))
|
||||
{
|
||||
typename BuffersType::mutable_buffers_type buffers (
|
||||
buffer.prepare (needed - available));
|
||||
buffer.commit (stream.read_some (buffers, ec));
|
||||
}
|
||||
}
|
||||
while (! ec);
|
||||
|
||||
return ec;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/** Asynchronous handshake detect.
|
||||
The bytes from the input sequence in the specified buffer
|
||||
are used first.
|
||||
|
||||
DetectHandler must have this signature:
|
||||
void(error_code)
|
||||
*/
|
||||
template <typename DetectHandler, typename Allocator>
|
||||
void async_detect (Stream& stream,
|
||||
boost::asio::basic_streambuf <Allocator>& buffer,
|
||||
BOOST_ASIO_MOVE_ARG(DetectHandler) handler)
|
||||
{
|
||||
async_detect <Allocator> (stream, buffer, SharedHandlerPtr (
|
||||
new ErrorSharedHandlerType <DetectHandler> (
|
||||
BOOST_ASIO_MOVE_CAST(DetectHandler)(handler))));
|
||||
}
|
||||
|
||||
template <typename Allocator>
|
||||
void async_detect (Stream& stream,
|
||||
boost::asio::basic_streambuf <Allocator>& buffer,
|
||||
SharedHandlerPtr handler)
|
||||
{
|
||||
typedef AsyncOp <Allocator> OpType;
|
||||
OpType* const op = new AsyncOp <Allocator> (
|
||||
m_logic, stream, buffer, handler);
|
||||
stream.get_io_service ().wrap (SharedHandlerPtr (op))
|
||||
(error_code (), 0);
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename Allocator>
|
||||
struct AsyncOp : ComposedAsyncOperation
|
||||
{
|
||||
typedef boost::asio::basic_streambuf <Allocator> BuffersType;
|
||||
|
||||
AsyncOp (HandshakeDetectLogicType <Logic>& logic, Stream& stream,
|
||||
BuffersType& buffer, SharedHandlerPtr const& handler)
|
||||
: ComposedAsyncOperation (sizeof (*this), handler)
|
||||
, m_logic (logic)
|
||||
, m_stream (stream)
|
||||
, m_buffer (buffer)
|
||||
, m_handler (handler)
|
||||
, m_running (false)
|
||||
{
|
||||
}
|
||||
|
||||
// Set breakpoint to prove it gets destroyed
|
||||
~AsyncOp ()
|
||||
{
|
||||
}
|
||||
|
||||
void operator() (error_code const& ec_, size_t bytes_transferred)
|
||||
{
|
||||
m_running = true;
|
||||
|
||||
error_code ec (ec_);
|
||||
|
||||
if (! ec)
|
||||
{
|
||||
m_buffer.commit (bytes_transferred);
|
||||
|
||||
m_logic.analyze (m_buffer.data ());
|
||||
|
||||
if (!m_logic.finished ())
|
||||
{
|
||||
std::size_t const available = m_buffer.size ();
|
||||
std::size_t const needed = m_logic.max_needed ();
|
||||
|
||||
// If postcondition fails, loop will never end
|
||||
if (meets_postcondition (available < needed))
|
||||
{
|
||||
typename BuffersType::mutable_buffers_type buffers (
|
||||
m_buffer.prepare (needed - available));
|
||||
|
||||
m_stream.async_read_some (buffers, SharedHandlerPtr (this));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::size_t const consumed = m_logic.bytes_consumed ();
|
||||
m_buffer.consume (consumed);
|
||||
}
|
||||
|
||||
// Finalize with a call to the original handler.
|
||||
m_stream.get_io_service ().wrap (
|
||||
BOOST_ASIO_MOVE_CAST (SharedHandlerPtr)(m_handler))
|
||||
(ec);
|
||||
}
|
||||
|
||||
bool is_continuation ()
|
||||
{
|
||||
return m_running
|
||||
#if BEAST_ASIO_HAS_CONTINUATION_HOOKS
|
||||
|| boost_asio_handler_cont_helpers::is_continuation (m_handler);
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
private:
|
||||
HandshakeDetectLogicType <Logic>& m_logic;
|
||||
Stream& m_stream;
|
||||
BuffersType& m_buffer;
|
||||
SharedHandlerPtr m_handler;
|
||||
bool m_running;
|
||||
};
|
||||
|
||||
private:
|
||||
HandshakeDetectLogicType <Logic> m_logic;
|
||||
};
|
||||
|
||||
#endif
|
||||
387
modules/beast_asio/protocol/InputParser.h
Normal file
387
modules/beast_asio/protocol/InputParser.h
Normal file
@@ -0,0 +1,387 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_HANDSHAKE_INPUTPARSER_H_INCLUDED
|
||||
#define BEAST_ASIO_HANDSHAKE_INPUTPARSER_H_INCLUDED
|
||||
|
||||
namespace InputParser
|
||||
{
|
||||
|
||||
/** Tri-valued parsing state.
|
||||
This is convertible to bool which means continue.
|
||||
Or you can use stop() to decide if you should return.
|
||||
After a stop you can use failed () to determine if parsing failed.
|
||||
*/
|
||||
struct State : SafeBool <State>
|
||||
{
|
||||
enum State_t
|
||||
{
|
||||
pass, // passed the parse
|
||||
fail, // failed the parse
|
||||
more // didn't fail but need more bytes
|
||||
};
|
||||
|
||||
State () : m_state (more) { }
|
||||
|
||||
State (State_t state) : m_state (state) { }
|
||||
|
||||
/** Implicit construction from bool.
|
||||
If condition is true then the parse passes, else need more.
|
||||
*/
|
||||
State (bool condition) : m_state (condition ? pass : more) { }
|
||||
|
||||
State& operator= (State_t state) { m_state = state; return *this; }
|
||||
|
||||
bool eof () const noexcept { return m_state == more; }
|
||||
bool stop () const noexcept { return m_state != pass; }
|
||||
bool passed () const noexcept { return m_state == pass; }
|
||||
bool failed () const noexcept { return m_state == fail; }
|
||||
bool asBoolean () const noexcept { return m_state == pass; } // for SafeBool<>
|
||||
|
||||
private:
|
||||
State_t m_state;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Shortcut to save typing.
|
||||
typedef FixedInputBuffer& Input;
|
||||
|
||||
/** Specializations implement the get() function. */
|
||||
template <class T>
|
||||
struct Get;
|
||||
|
||||
/** Specializations implement the match() function.
|
||||
Default implementation of match tries to read it into a local.
|
||||
*/
|
||||
template <class T>
|
||||
struct Match
|
||||
{
|
||||
static State func (Input in, T other)
|
||||
{
|
||||
T t;
|
||||
State state = Get <T>::func (in, t);
|
||||
if (state.passed ())
|
||||
{
|
||||
if (t == other)
|
||||
return State::pass;
|
||||
return State::fail;
|
||||
}
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
/** Specializations implement the peek() function.
|
||||
Default implementation of peek reads and rewinds.
|
||||
*/
|
||||
template <class T>
|
||||
struct Peek
|
||||
{
|
||||
static State func (Input in, T& t)
|
||||
{
|
||||
Input dup (in);
|
||||
return Get <T>::func (dup, t);
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Free Functions
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// match a block of data in memory
|
||||
//
|
||||
static State match_buffer (Input in, void const* buffer, std::size_t bytes)
|
||||
{
|
||||
bassert (bytes > 0);
|
||||
if (in.size () <= 0)
|
||||
return State::more;
|
||||
|
||||
std::size_t const have = std::min (in.size (), bytes);
|
||||
void const* data = in.peek (have);
|
||||
bassert (data != nullptr);
|
||||
|
||||
int const compare = memcmp (data, buffer, have);
|
||||
if (compare != 0)
|
||||
return State::fail;
|
||||
in.consume (have);
|
||||
|
||||
return have == bytes;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// match
|
||||
//
|
||||
|
||||
// Returns the state
|
||||
template <class T>
|
||||
State match (Input in, T t)
|
||||
{
|
||||
return Match <T>::func (in, t);
|
||||
}
|
||||
|
||||
// Stores the state in the argument and returns true if its a pass
|
||||
template <class T>
|
||||
bool match (Input in, T t, State& state)
|
||||
{
|
||||
return (state = match (in, t)).passed ();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// peek
|
||||
//
|
||||
|
||||
// Returns the state
|
||||
template <class T>
|
||||
State peek (Input in, T& t)
|
||||
{
|
||||
return Peek <T>::func (in, t);
|
||||
}
|
||||
|
||||
// Stores the state in the argument and returns true if its a pass
|
||||
template <class T>
|
||||
bool peek (Input in, T& t, State& state)
|
||||
{
|
||||
return (state = peek (in, t)).passed ();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// read
|
||||
//
|
||||
|
||||
// Returns the state
|
||||
template <class T>
|
||||
State read (Input in, T& t)
|
||||
{
|
||||
return Get <T>::func (in, t);
|
||||
}
|
||||
|
||||
// Stores the state in the argument and returns true if its a pass
|
||||
template <class T>
|
||||
bool read (Input in, T& t, State& state)
|
||||
{
|
||||
return (state = read (in, t)).passed ();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Specializations for basic types
|
||||
//
|
||||
|
||||
template <>
|
||||
struct Match <char const*>
|
||||
{
|
||||
static State func (Input in, char const* text)
|
||||
{
|
||||
return InputParser::match_buffer (in, text, strlen (text));
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Special types and their specializations
|
||||
//
|
||||
|
||||
struct Digit
|
||||
{
|
||||
int value;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Get <Digit>
|
||||
{
|
||||
static State func (Input in, Digit& t)
|
||||
{
|
||||
char c;
|
||||
if (! in.peek (&c))
|
||||
return State::more;
|
||||
if (! std::isdigit (c))
|
||||
return State::fail;
|
||||
in.consume (1);
|
||||
t.value = c - '0';
|
||||
return State::pass;
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// An unsigned 32 bit number expressed as a string
|
||||
struct UInt32Str
|
||||
{
|
||||
uint32 value;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Get <UInt32Str>
|
||||
{
|
||||
static State func (Input in, UInt32Str& t)
|
||||
{
|
||||
State state;
|
||||
uint32 value (0);
|
||||
|
||||
Digit digit;
|
||||
// have to have at least one digit
|
||||
if (! read (in, digit, state))
|
||||
return state;
|
||||
value = digit.value;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
state = peek (in, digit);
|
||||
|
||||
if (state.failed ())
|
||||
{
|
||||
t.value = value;
|
||||
return State::pass;
|
||||
}
|
||||
else if (state.eof ())
|
||||
{
|
||||
t.value = value;
|
||||
return state;
|
||||
}
|
||||
|
||||
// can't have a digit following a zero
|
||||
if (value == 0)
|
||||
return State::fail;
|
||||
|
||||
uint32 newValue = (value * 10) + digit.value;
|
||||
|
||||
// overflow
|
||||
if (newValue < value)
|
||||
return State::fail;
|
||||
|
||||
value = newValue;
|
||||
}
|
||||
|
||||
return State::fail;
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// An unsigned 16 bit number expressed as a string
|
||||
struct UInt16Str
|
||||
{
|
||||
uint16 value;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Get <UInt16Str>
|
||||
{
|
||||
static State func (Input in, UInt16Str& t)
|
||||
{
|
||||
UInt32Str v;
|
||||
State state = read (in, v);
|
||||
if (state.passed ())
|
||||
{
|
||||
if (v.value <= 65535)
|
||||
{
|
||||
t.value = uint16(v.value);
|
||||
return State::pass;
|
||||
}
|
||||
return State::fail;
|
||||
}
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// An unsigned 8 bit number expressed as a string
|
||||
struct UInt8Str
|
||||
{
|
||||
uint8 value;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Get <UInt8Str>
|
||||
{
|
||||
static State func (Input in, UInt8Str& t)
|
||||
{
|
||||
UInt32Str v;
|
||||
State state = read (in, v);
|
||||
if (state.passed ())
|
||||
{
|
||||
if (v.value <= 255)
|
||||
{
|
||||
t.value = uint8(v.value);
|
||||
return State::pass;
|
||||
}
|
||||
return State::fail;
|
||||
}
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// An dotted IPv4 address
|
||||
struct IPv4Address
|
||||
{
|
||||
uint8 value [4];
|
||||
|
||||
String toString () const
|
||||
{
|
||||
return String::fromNumber <int> (value [0]) + "." +
|
||||
String::fromNumber <int> (value [1]) + "." +
|
||||
String::fromNumber <int> (value [2]) + "." +
|
||||
String::fromNumber <int> (value [3]);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Get <IPv4Address>
|
||||
{
|
||||
static State func (Input in, IPv4Address& t)
|
||||
{
|
||||
State state;
|
||||
UInt8Str digit [4];
|
||||
if (! read (in, digit [0], state))
|
||||
return state;
|
||||
if (! match (in, ".", state))
|
||||
return state;
|
||||
if (! read (in, digit [1], state))
|
||||
return state;
|
||||
if (! match (in, ".", state))
|
||||
return state;
|
||||
if (! read (in, digit [2], state))
|
||||
return state;
|
||||
if (! match (in, ".", state))
|
||||
return state;
|
||||
if (! read (in, digit [3], state))
|
||||
return state;
|
||||
|
||||
t.value [0] = digit [0].value;
|
||||
t.value [1] = digit [1].value;
|
||||
t.value [2] = digit [2].value;
|
||||
t.value [3] = digit [3].value;
|
||||
|
||||
return State::pass;
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
197
modules/beast_asio/protocol/PrefilledReadStream.h
Normal file
197
modules/beast_asio/protocol/PrefilledReadStream.h
Normal file
@@ -0,0 +1,197 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_HANDSHAKE_PREFILLEDREADSTREAM_H_INCLUDED
|
||||
#define BEAST_ASIO_HANDSHAKE_PREFILLEDREADSTREAM_H_INCLUDED
|
||||
|
||||
/** Front-ends a stream with a provided block of data.
|
||||
|
||||
When read operations are performed on this object, bytes will first be
|
||||
returned from the buffer provided on construction. When those bytes
|
||||
are exhausted, read operations will then pass through to the underlying
|
||||
stream.
|
||||
|
||||
Write operations are all simply passed through.
|
||||
*/
|
||||
template <typename Stream>
|
||||
class PrefilledReadStream : public Uncopyable
|
||||
{
|
||||
protected:
|
||||
typedef boost::system::error_code error_code;
|
||||
|
||||
void throw_error (error_code const& ec, char const* fileName, int lineNumber)
|
||||
{
|
||||
Throw (boost::system::system_error (ec), fileName, lineNumber);
|
||||
}
|
||||
|
||||
public:
|
||||
typedef typename boost::remove_reference <Stream>::type next_layer_type;
|
||||
typedef typename next_layer_type::lowest_layer_type lowest_layer_type;
|
||||
|
||||
/** Single argument constructor for when we are wrapped in something.
|
||||
arg is passed through to the next layer's constructor.
|
||||
*/
|
||||
template <typename Arg>
|
||||
explicit PrefilledReadStream (Arg& arg)
|
||||
: m_next_layer (arg)
|
||||
{
|
||||
}
|
||||
|
||||
/** Construct with the buffer, and argument passed through.
|
||||
This creates a copy of the data. The argument is passed through
|
||||
to the constructor of Stream.
|
||||
*/
|
||||
template <typename Arg, typename ConstBufferSequence>
|
||||
PrefilledReadStream (Arg& arg, ConstBufferSequence const& buffers)
|
||||
: m_next_layer (arg)
|
||||
{
|
||||
fill (buffers);
|
||||
}
|
||||
|
||||
/** Place some input into the prefilled buffer.
|
||||
Note that this is in no way thread safe. The only reason this function
|
||||
is here is for the case when you can't pass the buffer through the
|
||||
constructor because there is another object wrapping this stream.
|
||||
*/
|
||||
template <typename ConstBufferSequence>
|
||||
void fill (ConstBufferSequence const& buffers)
|
||||
{
|
||||
// We don't assume the caller's buffers will
|
||||
// remain valid for the lifetime of this object.
|
||||
//
|
||||
using namespace boost;
|
||||
m_buffer.commit (asio::buffer_copy (
|
||||
m_buffer.prepare (asio::buffer_size (buffers)),
|
||||
buffers));
|
||||
}
|
||||
|
||||
next_layer_type& next_layer()
|
||||
{
|
||||
return m_next_layer;
|
||||
}
|
||||
|
||||
next_layer_type const& next_layer() const
|
||||
{
|
||||
return m_next_layer;
|
||||
}
|
||||
|
||||
lowest_layer_type& lowest_layer()
|
||||
{
|
||||
return m_next_layer.lowest_layer();
|
||||
}
|
||||
|
||||
const lowest_layer_type& lowest_layer() const
|
||||
{
|
||||
return m_next_layer.lowest_layer();
|
||||
}
|
||||
|
||||
boost::asio::io_service& get_io_service()
|
||||
{
|
||||
return m_next_layer.get_io_service();
|
||||
}
|
||||
|
||||
void close()
|
||||
{
|
||||
error_code ec;
|
||||
if (close(ec))
|
||||
throw_error (ec, __FILE__, __LINE__);
|
||||
return ec;
|
||||
}
|
||||
|
||||
error_code close (error_code& ec)
|
||||
{
|
||||
// VFALCO NOTE This is questionable. We can't
|
||||
// call m_next_layer.close() because Stream might not
|
||||
// support that function. For example, ssl::stream has no close()
|
||||
//
|
||||
return lowest_layer ().close(ec);
|
||||
}
|
||||
|
||||
template <typename MutableBufferSequence>
|
||||
std::size_t read_some (MutableBufferSequence const& buffers)
|
||||
{
|
||||
error_code ec;
|
||||
std::size_t const amount = read_some (buffers, ec);
|
||||
if (ec)
|
||||
throw_error (ec, __FILE__, __LINE__);
|
||||
return amount;
|
||||
}
|
||||
|
||||
template <typename MutableBufferSequence>
|
||||
std::size_t read_some (MutableBufferSequence const& buffers, error_code& ec)
|
||||
{
|
||||
if (m_buffer.size () > 0)
|
||||
{
|
||||
ec = error_code ();
|
||||
std::size_t const bytes_transferred = boost::asio::buffer_copy (
|
||||
buffers, m_buffer.data ());
|
||||
m_buffer.consume (bytes_transferred);
|
||||
return bytes_transferred;
|
||||
}
|
||||
return m_next_layer.read_some (buffers, ec);
|
||||
}
|
||||
|
||||
template <typename ConstBufferSequence>
|
||||
std::size_t write_some (ConstBufferSequence const& buffers)
|
||||
{
|
||||
error_code ec;
|
||||
std::size_t const amount = write_some (buffers, ec);
|
||||
if (ec)
|
||||
throw_error (ec, __FILE__, __LINE__);
|
||||
return amount;
|
||||
}
|
||||
|
||||
template <typename ConstBufferSequence>
|
||||
std::size_t write_some (ConstBufferSequence const& buffers, error_code& ec)
|
||||
{
|
||||
return m_next_layer.write_some (buffers, ec);
|
||||
}
|
||||
|
||||
template <typename MutableBufferSequence, typename ReadHandler>
|
||||
void async_read_some (MutableBufferSequence const& buffers,
|
||||
BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
|
||||
{
|
||||
if (m_buffer.size () > 0)
|
||||
{
|
||||
std::size_t const bytes_transferred = boost::asio::buffer_copy (
|
||||
buffers, m_buffer.data ());
|
||||
m_buffer.consume (bytes_transferred);
|
||||
get_io_service ().wrap (
|
||||
BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)) (
|
||||
error_code (), bytes_transferred);
|
||||
return;
|
||||
}
|
||||
m_next_layer.async_read_some (buffers,
|
||||
BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
|
||||
}
|
||||
|
||||
template <typename ConstBufferSequence, typename WriteHandler>
|
||||
void async_write_some (ConstBufferSequence const& buffers,
|
||||
BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
|
||||
{
|
||||
m_next_layer.async_write_some (buffers,
|
||||
BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
|
||||
}
|
||||
|
||||
private:
|
||||
Stream m_next_layer;
|
||||
boost::asio::streambuf m_buffer;
|
||||
};
|
||||
|
||||
#endif
|
||||
199
modules/beast_asio/sockets/Socket.cpp
Normal file
199
modules/beast_asio/sockets/Socket.cpp
Normal file
@@ -0,0 +1,199 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
Socket::~Socket ()
|
||||
{
|
||||
}
|
||||
|
||||
#if ! BEAST_COMPILER_CHECKS_SOCKET_OVERRIDES
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Socket
|
||||
//
|
||||
|
||||
void* Socket::this_layer_ptr (char const*) const
|
||||
{
|
||||
pure_virtual_called (__FILE__, __LINE__);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// native_handle
|
||||
//
|
||||
|
||||
bool Socket::native_handle (char const*, void*)
|
||||
{
|
||||
pure_virtual_called (__FILE__, __LINE__);
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// basic_io_object
|
||||
//
|
||||
|
||||
boost::asio::io_service& Socket::get_io_service ()
|
||||
{
|
||||
pure_virtual_called (__FILE__, __LINE__);
|
||||
return *static_cast <boost::asio::io_service*>(nullptr);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// basic_socket
|
||||
//
|
||||
|
||||
void* Socket::lowest_layer_ptr (char const*) const
|
||||
{
|
||||
pure_virtual_called (__FILE__, __LINE__);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
boost::system::error_code Socket::cancel (boost::system::error_code& ec)
|
||||
{
|
||||
return pure_virtual_error (ec, __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
boost::system::error_code Socket::shutdown (shutdown_type, boost::system::error_code& ec)
|
||||
{
|
||||
return pure_virtual_error (ec, __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
boost::system::error_code Socket::close (boost::system::error_code& ec)
|
||||
{
|
||||
return pure_virtual_error (ec, __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// basic_socket_acceptor
|
||||
//
|
||||
|
||||
boost::system::error_code Socket::accept (Socket&, boost::system::error_code& ec)
|
||||
{
|
||||
return pure_virtual_error (ec, __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
void Socket::async_accept (Socket&, SharedHandlerPtr handler)
|
||||
{
|
||||
get_io_service ().wrap (
|
||||
BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler))
|
||||
(pure_virtual_error ());
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// basic_stream_socket
|
||||
//
|
||||
|
||||
std::size_t Socket::read_some (MutableBuffers const&, boost::system::error_code& ec)
|
||||
{
|
||||
pure_virtual_called (__FILE__, __LINE__);
|
||||
ec = pure_virtual_error ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::size_t Socket::write_some (ConstBuffers const&, boost::system::error_code& ec)
|
||||
{
|
||||
pure_virtual_called (__FILE__, __LINE__);
|
||||
ec = pure_virtual_error ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Socket::async_read_some (MutableBuffers const&, SharedHandlerPtr handler)
|
||||
{
|
||||
get_io_service ().wrap (
|
||||
BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler))
|
||||
(pure_virtual_error (), 0);
|
||||
}
|
||||
|
||||
void Socket::async_write_some (ConstBuffers const&, SharedHandlerPtr handler)
|
||||
{
|
||||
get_io_service ().wrap (
|
||||
BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler))
|
||||
(pure_virtual_error (), 0);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// ssl::stream
|
||||
//
|
||||
|
||||
void* Socket::next_layer_ptr (char const*) const
|
||||
{
|
||||
pure_virtual_called (__FILE__, __LINE__);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool Socket::needs_handshake ()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void Socket::set_verify_mode (int)
|
||||
{
|
||||
pure_virtual_called (__FILE__, __LINE__);
|
||||
}
|
||||
|
||||
boost::system::error_code Socket::handshake (handshake_type, boost::system::error_code& ec)
|
||||
{
|
||||
return pure_virtual_error (ec, __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
void Socket::async_handshake (handshake_type, SharedHandlerPtr handler)
|
||||
{
|
||||
get_io_service ().wrap (
|
||||
BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler))
|
||||
(pure_virtual_error ());
|
||||
}
|
||||
|
||||
#if BEAST_ASIO_HAS_BUFFEREDHANDSHAKE
|
||||
|
||||
boost::system::error_code Socket::handshake (handshake_type,
|
||||
ConstBuffers const&, boost::system::error_code& ec)
|
||||
{
|
||||
return pure_virtual_error (ec, __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
void Socket::async_handshake (handshake_type, ConstBuffers const&, SharedHandlerPtr handler)
|
||||
{
|
||||
get_io_service ().wrap (
|
||||
BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler))
|
||||
(pure_virtual_error (), 0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
boost::system::error_code Socket::shutdown (boost::system::error_code& ec)
|
||||
{
|
||||
return pure_virtual_error (ec, __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
void Socket::async_shutdown (SharedHandlerPtr handler)
|
||||
{
|
||||
get_io_service ().wrap (
|
||||
BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler))
|
||||
(pure_virtual_error ());
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#endif
|
||||
436
modules/beast_asio/sockets/Socket.h
Normal file
436
modules/beast_asio/sockets/Socket.h
Normal file
@@ -0,0 +1,436 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_SOCKETS_SOCKET_H_INCLUDED
|
||||
#define BEAST_ASIO_SOCKETS_SOCKET_H_INCLUDED
|
||||
|
||||
/** A high level socket abstraction.
|
||||
|
||||
This combines the capabilities of multiple socket interfaces such
|
||||
as listening, connecting, streaming, and handshaking. It brings
|
||||
everything together into a single abstract interface.
|
||||
|
||||
When member functions are called and the underlying implementation does
|
||||
not support the operation, a fatal error is generated.
|
||||
*/
|
||||
class Socket
|
||||
: public SocketBase
|
||||
, public boost::asio::ssl::stream_base
|
||||
, public boost::asio::socket_base
|
||||
{
|
||||
public:
|
||||
virtual ~Socket ();
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// Socket
|
||||
//
|
||||
|
||||
/** Retrieve the underlying object.
|
||||
|
||||
@note If the type doesn't match, nullptr is returned or an
|
||||
exception is thrown if trying to acquire a reference.
|
||||
*/
|
||||
/** @{ */
|
||||
template <typename Object>
|
||||
Object& this_layer ()
|
||||
{
|
||||
Object* object (this->this_layer_ptr <Object> ());
|
||||
if (object == nullptr)
|
||||
Throw (std::bad_cast (), __FILE__, __LINE__);
|
||||
return *object;
|
||||
}
|
||||
|
||||
template <typename Object>
|
||||
Object const& this_layer () const
|
||||
{
|
||||
Object const* object (this->this_layer_ptr <Object> ());
|
||||
if (object == nullptr)
|
||||
Throw (std::bad_cast (), __FILE__, __LINE__);
|
||||
return *object;
|
||||
}
|
||||
|
||||
template <typename Object>
|
||||
Object* this_layer_ptr ()
|
||||
{
|
||||
return static_cast <Object*> (
|
||||
this->this_layer_ptr (typeid (Object).name ()));
|
||||
}
|
||||
|
||||
template <typename Object>
|
||||
Object const* this_layer_ptr () const
|
||||
{
|
||||
return static_cast <Object const*> (
|
||||
this->this_layer_ptr (typeid (Object).name ()));
|
||||
}
|
||||
/** @} */
|
||||
|
||||
virtual void* this_layer_ptr (char const* type_name) const
|
||||
BEAST_SOCKET_VIRTUAL;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// native_handle
|
||||
//
|
||||
|
||||
/** Retrieve the native representation of the object.
|
||||
|
||||
Since we dont know the return type, and because almost every
|
||||
asio implementation passes the result by value, you need to provide
|
||||
a pointer to a default-constructed object of the matching type.
|
||||
|
||||
@note If the type doesn't match, an exception is thrown.
|
||||
*/
|
||||
template <typename Handle>
|
||||
void native_handle (Handle* dest)
|
||||
{
|
||||
if (! native_handle (typeid (Handle).name (), dest))
|
||||
Throw (std::bad_cast (), __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
virtual bool native_handle (char const* type_name, void* dest)
|
||||
BEAST_SOCKET_VIRTUAL;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// basic_io_object
|
||||
//
|
||||
|
||||
virtual boost::asio::io_service& get_io_service ()
|
||||
BEAST_SOCKET_VIRTUAL;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// basic_socket
|
||||
//
|
||||
|
||||
/** Retrieve the lowest layer object.
|
||||
|
||||
@note If the type doesn't match, nullptr is returned or an
|
||||
exception is thrown if trying to acquire a reference.
|
||||
*/
|
||||
/** @{ */
|
||||
template <typename Object>
|
||||
Object& lowest_layer ()
|
||||
{
|
||||
Object* object (this->lowest_layer_ptr <Object> ());
|
||||
if (object == nullptr)
|
||||
Throw (std::bad_cast (), __FILE__, __LINE__);
|
||||
return *object;
|
||||
}
|
||||
|
||||
template <typename Object>
|
||||
Object const& lowest_layer () const
|
||||
{
|
||||
Object const* object (this->lowest_layer_ptr <Object> ());
|
||||
if (object == nullptr)
|
||||
Throw (std::bad_cast (), __FILE__, __LINE__);
|
||||
return *object;
|
||||
}
|
||||
|
||||
template <typename Object>
|
||||
Object* lowest_layer_ptr ()
|
||||
{
|
||||
return static_cast <Object*> (
|
||||
this->lowest_layer_ptr (typeid (Object).name ()));
|
||||
}
|
||||
|
||||
template <typename Object>
|
||||
Object const* lowest_layer_ptr () const
|
||||
{
|
||||
return static_cast <Object const*> (
|
||||
this->lowest_layer_ptr (typeid (Object).name ()));
|
||||
}
|
||||
/** @} */
|
||||
|
||||
virtual void* lowest_layer_ptr (char const* type_name) const
|
||||
BEAST_SOCKET_VIRTUAL;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void cancel ()
|
||||
{
|
||||
error_code ec;
|
||||
throw_error (cancel (ec), __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
virtual error_code cancel (error_code& ec)
|
||||
BEAST_SOCKET_VIRTUAL;
|
||||
|
||||
void shutdown (shutdown_type what)
|
||||
{
|
||||
error_code ec;
|
||||
throw_error (shutdown (what, ec), __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
virtual error_code shutdown (shutdown_type what,
|
||||
error_code& ec)
|
||||
BEAST_SOCKET_VIRTUAL;
|
||||
|
||||
void close ()
|
||||
{
|
||||
error_code ec;
|
||||
throw_error (close (ec), __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
virtual error_code close (error_code& ec)
|
||||
BEAST_SOCKET_VIRTUAL;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// basic_socket_acceptor
|
||||
//
|
||||
|
||||
virtual error_code accept (Socket& peer, error_code& ec)
|
||||
BEAST_SOCKET_VIRTUAL;
|
||||
|
||||
template <typename AcceptHandler>
|
||||
void async_accept (Socket& peer, BOOST_ASIO_MOVE_ARG(AcceptHandler) handler)
|
||||
{
|
||||
return async_accept (peer,
|
||||
newAcceptHandler (BOOST_ASIO_MOVE_CAST(AcceptHandler)(handler)));
|
||||
}
|
||||
|
||||
virtual void async_accept (Socket& peer, SharedHandlerPtr handler)
|
||||
BEAST_SOCKET_VIRTUAL;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// basic_stream_socket
|
||||
//
|
||||
|
||||
// SyncReadStream
|
||||
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/SyncReadStream.html
|
||||
//
|
||||
template <typename MutableBufferSequence>
|
||||
std::size_t read_some (MutableBufferSequence const& buffers,
|
||||
error_code& ec)
|
||||
{
|
||||
return read_some (MutableBuffers (buffers), ec);
|
||||
}
|
||||
|
||||
virtual std::size_t read_some (MutableBuffers const& buffers, error_code& ec)
|
||||
BEAST_SOCKET_VIRTUAL;
|
||||
|
||||
// SyncWriteStream
|
||||
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/SyncWriteStream.html
|
||||
//
|
||||
template <typename ConstBufferSequence>
|
||||
std::size_t write_some (ConstBufferSequence const& buffers, error_code &ec)
|
||||
{
|
||||
return write_some (ConstBuffers (buffers), ec);
|
||||
}
|
||||
|
||||
virtual std::size_t write_some (ConstBuffers const& buffers, error_code& ec)
|
||||
BEAST_SOCKET_VIRTUAL;
|
||||
|
||||
// AsyncReadStream
|
||||
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/AsyncReadStream.html
|
||||
//
|
||||
template <typename MutableBufferSequence, typename ReadHandler>
|
||||
void async_read_some (MutableBufferSequence const& buffers,
|
||||
BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
|
||||
{
|
||||
return async_read_some (MutableBuffers (buffers),
|
||||
newReadHandler (BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)));
|
||||
}
|
||||
|
||||
virtual void async_read_some (MutableBuffers const& buffers, SharedHandlerPtr handler)
|
||||
BEAST_SOCKET_VIRTUAL;
|
||||
|
||||
// AsyncWriteStream
|
||||
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/AsyncWriteStream.html
|
||||
//
|
||||
template <typename ConstBufferSequence, typename WriteHandler>
|
||||
void async_write_some (ConstBufferSequence const& buffers,
|
||||
BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
|
||||
{
|
||||
return async_write_some (ConstBuffers (buffers),
|
||||
newWriteHandler (BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)));
|
||||
}
|
||||
|
||||
virtual void async_write_some (ConstBuffers const& buffers, SharedHandlerPtr handler)
|
||||
BEAST_SOCKET_VIRTUAL;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// ssl::stream
|
||||
//
|
||||
|
||||
/** Retrieve the next layer object.
|
||||
|
||||
@note If the type doesn't match, nullptr is returned or an
|
||||
exception is thrown if trying to acquire a reference.
|
||||
*/
|
||||
/** @{ */
|
||||
template <typename Object>
|
||||
Object& next_layer ()
|
||||
{
|
||||
Object* object (this->next_layer_ptr <Object> ());
|
||||
if (object == nullptr)
|
||||
Throw (std::bad_cast (), __FILE__, __LINE__);
|
||||
return *object;
|
||||
}
|
||||
|
||||
template <typename Object>
|
||||
Object const& next_layer () const
|
||||
{
|
||||
Object const* object (this->next_layer_ptr <Object> ());
|
||||
if (object == nullptr)
|
||||
Throw (std::bad_cast (), __FILE__, __LINE__);
|
||||
return *object;
|
||||
}
|
||||
|
||||
template <typename Object>
|
||||
Object* next_layer_ptr ()
|
||||
{
|
||||
return static_cast <Object*> (
|
||||
this->next_layer_ptr (typeid (Object).name ()));
|
||||
}
|
||||
|
||||
template <typename Object>
|
||||
Object const* next_layer_ptr () const
|
||||
{
|
||||
return static_cast <Object const*> (
|
||||
this->next_layer_ptr (typeid (Object).name ()));
|
||||
}
|
||||
/** @} */
|
||||
|
||||
virtual void* next_layer_ptr (char const* type_name) const
|
||||
BEAST_SOCKET_VIRTUAL;
|
||||
|
||||
/** Determines if the underlying stream requires a handshake.
|
||||
|
||||
If needs_handshake is true, it will be necessary to call handshake or
|
||||
async_handshake after the connection is established. Furthermore it
|
||||
will be necessary to call the shutdown member from the
|
||||
HandshakeInterface to close the connection. Do not close the underlying
|
||||
socket or else the closure will not be graceful. Only one side should
|
||||
initiate the handshaking shutdon. The other side should observe it.
|
||||
Which side does what is up to the user.
|
||||
|
||||
The default version returns false.
|
||||
*/
|
||||
virtual bool needs_handshake ()
|
||||
BEAST_SOCKET_VIRTUAL;
|
||||
|
||||
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ssl__verify_mode.html
|
||||
//
|
||||
virtual void set_verify_mode (int verify_mode) = 0;
|
||||
|
||||
// ssl::stream::handshake (1 of 4)
|
||||
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ssl__stream/handshake/overload1.html
|
||||
//
|
||||
void handshake (handshake_type type)
|
||||
{
|
||||
error_code ec;
|
||||
throw_error (handshake (type, ec), __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
// ssl::stream::handshake (2 of 4)
|
||||
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ssl__stream/handshake/overload2.html
|
||||
//
|
||||
virtual error_code handshake (handshake_type type, error_code& ec)
|
||||
BEAST_SOCKET_VIRTUAL;
|
||||
|
||||
// ssl::stream::async_handshake (1 of 2)
|
||||
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ssl__stream/async_handshake/overload1.html
|
||||
//
|
||||
template <typename HandshakeHandler>
|
||||
void async_handshake (handshake_type type, BOOST_ASIO_MOVE_ARG(HandshakeHandler) handler)
|
||||
{
|
||||
return async_handshake (type,
|
||||
newHandshakeHandler (BOOST_ASIO_MOVE_CAST(HandshakeHandler)(handler)));
|
||||
}
|
||||
|
||||
virtual void async_handshake (handshake_type type, SharedHandlerPtr handler)
|
||||
BEAST_SOCKET_VIRTUAL;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
#if BEAST_ASIO_HAS_BUFFEREDHANDSHAKE
|
||||
// ssl::stream::handshake (3 of 4)
|
||||
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ssl__stream/handshake/overload3.html
|
||||
//
|
||||
template <typename ConstBufferSequence>
|
||||
void handshake (handshake_type type, ConstBufferSequence const& buffers)
|
||||
{
|
||||
error_code ec;
|
||||
throw_error (handshake (type, buffers, ec), __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
// ssl::stream::handshake (4 of 4)
|
||||
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ssl__stream/handshake/overload4.html
|
||||
//
|
||||
template <typename ConstBufferSequence>
|
||||
error_code handshake (handshake_type type,
|
||||
ConstBufferSequence const& buffers, error_code& ec)
|
||||
{
|
||||
return handshake (type, ConstBuffers (buffers), ec);
|
||||
}
|
||||
|
||||
virtual error_code handshake (handshake_type type,
|
||||
ConstBuffers const& buffers, error_code& ec)
|
||||
BEAST_SOCKET_VIRTUAL;
|
||||
|
||||
// ssl::stream::async_handshake (2 of 2)
|
||||
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ssl__stream/async_handshake/overload2.html
|
||||
//
|
||||
template <typename ConstBufferSequence, typename BufferedHandshakeHandler>
|
||||
void async_handshake (handshake_type type, ConstBufferSequence const& buffers,
|
||||
BOOST_ASIO_MOVE_ARG(BufferedHandshakeHandler) handler)
|
||||
{
|
||||
return async_handshake (type, ConstBuffers (buffers),
|
||||
newBufferedHandshakeHandler (BOOST_ASIO_MOVE_CAST(BufferedHandshakeHandler)(handler)));
|
||||
}
|
||||
|
||||
virtual void async_handshake (handshake_type type, ConstBuffers const& buffers,
|
||||
SharedHandlerPtr handler)
|
||||
BEAST_SOCKET_VIRTUAL;
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
// ssl::stream::shutdown
|
||||
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ssl__stream/shutdown.html
|
||||
//
|
||||
void shutdown ()
|
||||
{
|
||||
error_code ec;
|
||||
throw_error (shutdown (ec), __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
virtual error_code shutdown (error_code& ec)
|
||||
BEAST_SOCKET_VIRTUAL;
|
||||
|
||||
// ssl::stream::async_shutdown
|
||||
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ssl__stream/async_shutdown.html
|
||||
//
|
||||
template <typename ShutdownHandler>
|
||||
void async_shutdown (BOOST_ASIO_MOVE_ARG(ShutdownHandler) handler)
|
||||
{
|
||||
return async_shutdown (
|
||||
newShutdownHandler (BOOST_ASIO_MOVE_CAST(ShutdownHandler)(handler)));
|
||||
}
|
||||
|
||||
virtual void async_shutdown (SharedHandlerPtr handler)
|
||||
BEAST_SOCKET_VIRTUAL;
|
||||
};
|
||||
|
||||
#endif
|
||||
42
modules/beast_asio/sockets/SocketBase.cpp
Normal file
42
modules/beast_asio/sockets/SocketBase.cpp
Normal file
@@ -0,0 +1,42 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
boost::system::error_code SocketBase::pure_virtual_error ()
|
||||
{
|
||||
return boost::system::errc::make_error_code (
|
||||
boost::system::errc::function_not_supported);
|
||||
}
|
||||
|
||||
boost::system::error_code SocketBase::pure_virtual_error (error_code& ec,
|
||||
char const* fileName, int lineNumber)
|
||||
{
|
||||
pure_virtual_called (fileName, lineNumber);
|
||||
return ec = pure_virtual_error ();
|
||||
}
|
||||
|
||||
void SocketBase::pure_virtual_called (char const* fileName, int lineNumber)
|
||||
{
|
||||
Throw (std::runtime_error ("pure virtual called"), fileName, lineNumber);
|
||||
}
|
||||
|
||||
void SocketBase::throw_error (error_code const& ec, char const* fileName, int lineNumber)
|
||||
{
|
||||
if (ec)
|
||||
Throw (boost::system::system_error (ec), fileName, lineNumber);
|
||||
}
|
||||
49
modules/beast_asio/sockets/SocketBase.h
Normal file
49
modules/beast_asio/sockets/SocketBase.h
Normal file
@@ -0,0 +1,49 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_SOCKETS_SOCKETBASE_H_INCLUDED
|
||||
#define BEAST_ASIO_SOCKETS_SOCKETBASE_H_INCLUDED
|
||||
|
||||
/** Common implementation details for Socket and related classes.
|
||||
Normally you wont need to use this.
|
||||
*/
|
||||
struct SocketBase
|
||||
{
|
||||
protected:
|
||||
typedef boost::system::error_code error_code;
|
||||
|
||||
/** The error returned when a pure virtual is called.
|
||||
This is mostly academic since a pure virtual call generates
|
||||
a fatal error but in case that gets disabled, this will at
|
||||
least return a suitable error code.
|
||||
*/
|
||||
static error_code pure_virtual_error ();
|
||||
|
||||
/** Convenience for taking a reference and returning the error_code. */
|
||||
static error_code pure_virtual_error (error_code& ec,
|
||||
char const* fileName, int lineNumber);
|
||||
|
||||
/** Called when a function doesn't support the interface. */
|
||||
static void pure_virtual_called (char const* fileName, int lineNumber);
|
||||
|
||||
/** Called when synchronous functions without error parameters get an error. */
|
||||
static void throw_error (error_code const& ec, char const* fileName, int lineNumber);
|
||||
};
|
||||
|
||||
#endif
|
||||
838
modules/beast_asio/sockets/SocketWrapper.h
Normal file
838
modules/beast_asio/sockets/SocketWrapper.h
Normal file
@@ -0,0 +1,838 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_SOCKETS_SOCKETWRAPPER_H_INCLUDED
|
||||
#define BEAST_ASIO_SOCKETS_SOCKETWRAPPER_H_INCLUDED
|
||||
|
||||
/** Wraps a reference to any object and exports all availble interfaces.
|
||||
|
||||
If the object does not support an interface, calling those
|
||||
member functions will behave as if a pure virtual was called.
|
||||
|
||||
Note that only a reference to the underlying is stored. Management
|
||||
of the lifetime of the object is controlled by the caller.
|
||||
|
||||
Examples of the type of Object:
|
||||
|
||||
asio::ip::tcp::socket
|
||||
asio::ip::tcp::socket&
|
||||
asio::ssl::stream <asio::ip::tcp::socket>
|
||||
asio::ssl::stream <asio::ip::tcp::socket&>
|
||||
explain arg must be an io_context
|
||||
explain SocketWrapper will create and take ownership of the tcp::socket
|
||||
explain this_layer_type will be tcp::socket
|
||||
explain next_layer () returns a asio::ip::tcp::socket&
|
||||
explain lowest_layer () returns a asio::ip::tcp::socket&
|
||||
|
||||
asio::ssl::stream <asio::buffered_stream <asio::ip::tcp::socket> > >
|
||||
This makes my head explode
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
namespace SocketWrapperMemberChecks
|
||||
{
|
||||
template <bool Enable>
|
||||
struct EnableIf : boost::false_type { };
|
||||
|
||||
template <>
|
||||
struct EnableIf <true> : boost::true_type { };
|
||||
|
||||
BEAST_DEFINE_IS_CALL_POSSIBLE(has_get_io_service, get_io_service);
|
||||
|
||||
BEAST_DEFINE_IS_CALL_POSSIBLE(has_lowest_layer, lowest_layer);
|
||||
BEAST_DEFINE_IS_CALL_POSSIBLE(has_cancel, cancel);
|
||||
BEAST_DEFINE_IS_CALL_POSSIBLE(has_shutdown, shutdown);
|
||||
BEAST_DEFINE_IS_CALL_POSSIBLE(has_close, close);
|
||||
|
||||
BEAST_DEFINE_IS_CALL_POSSIBLE(has_accept, accept);
|
||||
BEAST_DEFINE_IS_CALL_POSSIBLE(has_async_accept, async_accept);
|
||||
|
||||
BEAST_DEFINE_IS_CALL_POSSIBLE(has_read_some, read_some);
|
||||
BEAST_DEFINE_IS_CALL_POSSIBLE(has_write_some, write_some);
|
||||
BEAST_DEFINE_IS_CALL_POSSIBLE(has_async_read_some, async_read_some);
|
||||
BEAST_DEFINE_IS_CALL_POSSIBLE(has_async_write_some, async_write_some);
|
||||
|
||||
BEAST_DEFINE_IS_CALL_POSSIBLE(has_set_verify_mode, set_verify_mode);
|
||||
BEAST_DEFINE_IS_CALL_POSSIBLE(has_handshake, handshake);
|
||||
BEAST_DEFINE_IS_CALL_POSSIBLE(has_async_handshake, async_handshake);
|
||||
BEAST_DEFINE_IS_CALL_POSSIBLE(has_async_shutdown, async_shutdown);
|
||||
|
||||
// Extracts the underlying socket type from the protocol of another asio object
|
||||
template <typename T, typename Enable = void>
|
||||
struct native_socket
|
||||
{
|
||||
typedef void* socket_type;
|
||||
inline native_socket (Socket&)
|
||||
: m_socket (nullptr)
|
||||
{
|
||||
SocketBase::pure_virtual_called (__FILE__, __LINE__);
|
||||
}
|
||||
inline socket_type& get ()
|
||||
{
|
||||
SocketBase::pure_virtual_called (__FILE__, __LINE__);
|
||||
return m_socket;
|
||||
}
|
||||
inline socket_type& operator-> ()
|
||||
{
|
||||
return get ();
|
||||
}
|
||||
private:
|
||||
socket_type m_socket;
|
||||
};
|
||||
|
||||
// Enabled if T::protocol_type::socket exists as a type
|
||||
template <typename T>
|
||||
struct native_socket <T, typename boost::enable_if <boost::is_class <
|
||||
typename T::protocol_type::socket> >::type>
|
||||
{
|
||||
typedef typename T::protocol_type::socket socket_type;
|
||||
inline native_socket (Socket& peer)
|
||||
: m_socket_ptr (&peer.this_layer <socket_type> ())
|
||||
{
|
||||
}
|
||||
inline socket_type& get () noexcept
|
||||
{
|
||||
return *m_socket_ptr;
|
||||
}
|
||||
inline socket_type& operator-> () noexcept
|
||||
{
|
||||
return get ();
|
||||
}
|
||||
private:
|
||||
socket_type* m_socket_ptr;
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <typename Object>
|
||||
class SocketWrapper
|
||||
: public Socket
|
||||
, public Uncopyable
|
||||
{
|
||||
public:
|
||||
template <typename Arg>
|
||||
explicit SocketWrapper (Arg& arg)
|
||||
: m_object (arg)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Arg1, typename Arg2>
|
||||
SocketWrapper (Arg1& arg1, Arg2& arg2)
|
||||
: m_object (arg1, arg2)
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// SocketWrapper
|
||||
//
|
||||
|
||||
/** The type of the object being wrapped. */
|
||||
typedef typename boost::remove_reference <Object>::type this_layer_type;
|
||||
|
||||
/** Get a reference to this layer. */
|
||||
this_layer_type& this_layer () noexcept
|
||||
{
|
||||
return m_object;
|
||||
}
|
||||
|
||||
/** Get a const reference to this layer. */
|
||||
this_layer_type const& this_layer () const noexcept
|
||||
{
|
||||
return m_object;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// Socket
|
||||
//
|
||||
|
||||
void* this_layer_ptr (char const* type_name) const
|
||||
{
|
||||
char const* const name (typeid (this_layer_type).name ());
|
||||
if (strcmp (name, type_name) == 0)
|
||||
return const_cast <void*> (static_cast <void const*> (&m_object));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// native_handle
|
||||
//
|
||||
|
||||
#if 0
|
||||
// This is a potential work-around for the problem with
|
||||
// the has_type_native_handle_type template, but requires
|
||||
// Boost 1.54 or later.
|
||||
//
|
||||
// This include will be needed:
|
||||
//
|
||||
// boost/tti/has_type.hpp
|
||||
//
|
||||
//
|
||||
BOOST_TTI_HAS_TYPE(native_handle_type)
|
||||
|
||||
#else
|
||||
template <class T>
|
||||
struct has_type_native_handle_type
|
||||
{
|
||||
typedef char yes;
|
||||
typedef struct {char dummy[2];} no;
|
||||
template <class C> static yes f(typename C::native_handle_type*);
|
||||
template <class C> static no f(...);
|
||||
#ifdef _MSC_VER
|
||||
static bool const value = sizeof(f<T>(0)) == 1;
|
||||
#else
|
||||
// This line fails to compile under Visual Studio 2012
|
||||
static bool const value = sizeof(has_type_native_handle_type<T>::f<T>(0)) == 1;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
template <typename T, bool Exists = has_type_native_handle_type <T>::value >
|
||||
struct extract_native_handle_type
|
||||
{
|
||||
typedef typename T::native_handle_type type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct extract_native_handle_type <T, false>
|
||||
{
|
||||
typedef void type;
|
||||
};
|
||||
|
||||
// This will be void if native_handle_type doesn't exist in Object
|
||||
typedef typename extract_native_handle_type <this_layer_type>::type native_handle_type;
|
||||
|
||||
bool native_handle (char const* type_name, void* dest)
|
||||
{
|
||||
using namespace detail::SocketWrapperMemberChecks;
|
||||
return native_handle (type_name, dest,
|
||||
EnableIf <has_type_native_handle_type <this_layer_type>::value> ());
|
||||
}
|
||||
|
||||
bool native_handle (char const* type_name, void* dest,
|
||||
boost::true_type)
|
||||
{
|
||||
char const* const name (typeid (typename this_layer_type::native_handle_type).name ());
|
||||
if (strcmp (name, type_name) == 0)
|
||||
{
|
||||
native_handle_type* const p (reinterpret_cast <native_handle_type*> (dest));
|
||||
*p = m_object.native_handle ();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool native_handle (char const*, void*,
|
||||
boost::false_type)
|
||||
{
|
||||
pure_virtual_called (__FILE__, __LINE__);
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// basic_io_object
|
||||
//
|
||||
|
||||
boost::asio::io_service& get_io_service ()
|
||||
{
|
||||
#if 0
|
||||
// Apparently has_get_io_service always results in false
|
||||
using namespace detail::SocketWrapperMemberChecks;
|
||||
return get_io_service (
|
||||
EnableIf <has_get_io_service <this_layer_type,
|
||||
boost::asio::io_service&()>::value> ());
|
||||
#else
|
||||
return get_io_service (boost::true_type ());
|
||||
#endif
|
||||
}
|
||||
|
||||
boost::asio::io_service& get_io_service (
|
||||
boost::true_type)
|
||||
{
|
||||
return m_object.get_io_service ();
|
||||
}
|
||||
|
||||
boost::asio::io_service& get_io_service (
|
||||
boost::false_type)
|
||||
{
|
||||
pure_virtual_called (__FILE__, __LINE__);
|
||||
return *static_cast <boost::asio::io_service*>(nullptr);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// basic_socket
|
||||
//
|
||||
|
||||
/*
|
||||
To forward the lowest_layer_type type, we need to make sure it
|
||||
exists in Object. This is a little more tricky than just figuring
|
||||
out if Object has a particular member function.
|
||||
|
||||
The problem is boost::asio::basic_socket_acceptor, which doesn't
|
||||
have lowest_layer () or lowest_layer_type ().
|
||||
*/
|
||||
|
||||
template <class T>
|
||||
struct has_type_lowest_layer_type
|
||||
{
|
||||
typedef char yes;
|
||||
typedef struct {char dummy[2];} no;
|
||||
template <class C> static yes f(typename C::lowest_layer_type*);
|
||||
template <class C> static no f(...);
|
||||
#ifdef _MSC_VER
|
||||
static bool const value = sizeof(f<T>(0)) == 1;
|
||||
#else
|
||||
// This line fails to compile under Visual Studio 2012
|
||||
static bool const value = sizeof(has_type_lowest_layer_type<T>::f<T>(0)) == 1;
|
||||
#endif
|
||||
};
|
||||
|
||||
template <typename T, bool Exists = has_type_lowest_layer_type <T>::value >
|
||||
struct extract_lowest_layer_type
|
||||
{
|
||||
typedef typename T::lowest_layer_type type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct extract_lowest_layer_type <T, false>
|
||||
{
|
||||
typedef void type;
|
||||
};
|
||||
|
||||
// This will be void if lowest_layer_type doesn't exist in Object
|
||||
typedef typename extract_lowest_layer_type <this_layer_type>::type lowest_layer_type;
|
||||
|
||||
void* lowest_layer_ptr (char const* type_name) const
|
||||
{
|
||||
using namespace detail::SocketWrapperMemberChecks;
|
||||
return lowest_layer_ptr (type_name,
|
||||
EnableIf <has_type_lowest_layer_type <this_layer_type>::value> ());
|
||||
}
|
||||
|
||||
void* lowest_layer_ptr (char const* type_name,
|
||||
boost::true_type) const
|
||||
{
|
||||
char const* const name (typeid (typename this_layer_type::lowest_layer_type).name ());
|
||||
if (strcmp (name, type_name) == 0)
|
||||
return const_cast <void*> (static_cast <void const*> (&m_object.lowest_layer ()));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void* lowest_layer_ptr (char const*,
|
||||
boost::false_type) const
|
||||
{
|
||||
pure_virtual_called (__FILE__, __LINE__);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
error_code cancel (error_code& ec)
|
||||
{
|
||||
using namespace detail::SocketWrapperMemberChecks;
|
||||
return cancel (ec,
|
||||
EnableIf <has_cancel <this_layer_type,
|
||||
error_code (error_code&)>::value> ());
|
||||
}
|
||||
|
||||
error_code cancel (error_code& ec,
|
||||
boost::true_type)
|
||||
{
|
||||
return m_object.cancel (ec);
|
||||
}
|
||||
|
||||
error_code cancel (error_code& ec,
|
||||
boost::false_type)
|
||||
{
|
||||
return pure_virtual_error (ec, __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
error_code shutdown (shutdown_type what, error_code& ec)
|
||||
{
|
||||
using namespace detail::SocketWrapperMemberChecks;
|
||||
return shutdown (what, ec,
|
||||
EnableIf <has_shutdown <this_layer_type,
|
||||
error_code (shutdown_type, error_code&)>::value> ());
|
||||
}
|
||||
|
||||
|
||||
error_code shutdown (shutdown_type what, error_code& ec,
|
||||
boost::true_type)
|
||||
{
|
||||
return m_object.shutdown (what, ec);
|
||||
}
|
||||
|
||||
error_code shutdown (shutdown_type, error_code& ec,
|
||||
boost::false_type)
|
||||
{
|
||||
return pure_virtual_error (ec, __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
error_code close (error_code& ec)
|
||||
{
|
||||
using namespace detail::SocketWrapperMemberChecks;
|
||||
return close (ec,
|
||||
EnableIf <has_close <this_layer_type,
|
||||
error_code (error_code&)>::value> ());
|
||||
}
|
||||
|
||||
error_code close (error_code& ec,
|
||||
boost::true_type)
|
||||
{
|
||||
return m_object.close (ec);
|
||||
}
|
||||
|
||||
error_code close (error_code& ec,
|
||||
boost::false_type)
|
||||
{
|
||||
return pure_virtual_error (ec, __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// basic_socket_acceptor
|
||||
//
|
||||
|
||||
error_code accept (Socket& peer, error_code& ec)
|
||||
{
|
||||
using namespace detail::SocketWrapperMemberChecks;
|
||||
typedef typename native_socket <this_layer_type>::socket_type socket_type;
|
||||
return accept (peer, ec,
|
||||
EnableIf <has_accept <this_layer_type,
|
||||
error_code (socket_type&, error_code&)>::value> ());
|
||||
}
|
||||
|
||||
error_code accept (Socket& peer, error_code& ec,
|
||||
boost::true_type)
|
||||
{
|
||||
using namespace detail::SocketWrapperMemberChecks;
|
||||
return m_object.accept (
|
||||
native_socket <this_layer_type> (peer).get (), ec);
|
||||
}
|
||||
|
||||
error_code accept (Socket&, error_code& ec,
|
||||
boost::false_type)
|
||||
{
|
||||
return pure_virtual_error (ec, __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void async_accept (Socket& peer, SharedHandlerPtr handler)
|
||||
{
|
||||
using namespace detail::SocketWrapperMemberChecks;
|
||||
typedef typename native_socket <this_layer_type>::socket_type socket_type;
|
||||
async_accept (peer, BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler),
|
||||
EnableIf <has_async_accept <this_layer_type,
|
||||
void (socket_type&, BOOST_ASIO_MOVE_ARG(SharedHandlerPtr))>::value> ());
|
||||
}
|
||||
|
||||
void async_accept (Socket& peer, BOOST_ASIO_MOVE_ARG(SharedHandlerPtr) handler,
|
||||
boost::true_type)
|
||||
{
|
||||
using namespace detail::SocketWrapperMemberChecks;
|
||||
m_object.async_accept (
|
||||
native_socket <this_layer_type> (peer).get (),
|
||||
BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler));
|
||||
}
|
||||
|
||||
void async_accept (Socket&, BOOST_ASIO_MOVE_ARG(SharedHandlerPtr) handler,
|
||||
boost::false_type)
|
||||
{
|
||||
get_io_service ().wrap (
|
||||
BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler))
|
||||
(pure_virtual_error ());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// basic_stream_socket
|
||||
//
|
||||
|
||||
std::size_t read_some (MutableBuffers const& buffers, error_code& ec)
|
||||
{
|
||||
using namespace detail::SocketWrapperMemberChecks;
|
||||
return read_some (buffers, ec,
|
||||
EnableIf <has_read_some <this_layer_type,
|
||||
std::size_t (MutableBuffers const&, error_code&)>::value> ());
|
||||
}
|
||||
|
||||
template <typename MutableBufferSequence>
|
||||
std::size_t read_some (MutableBufferSequence const& buffers, error_code& ec,
|
||||
boost::true_type)
|
||||
{
|
||||
return m_object.read_some (buffers, ec);
|
||||
}
|
||||
|
||||
template <typename MutableBufferSequence>
|
||||
std::size_t read_some (MutableBufferSequence const&, error_code& ec,
|
||||
boost::false_type)
|
||||
{
|
||||
pure_virtual_called (__FILE__, __LINE__);
|
||||
ec = pure_virtual_error ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
std::size_t write_some (ConstBuffers const& buffers, error_code& ec)
|
||||
{
|
||||
using namespace detail::SocketWrapperMemberChecks;
|
||||
return write_some (buffers, ec,
|
||||
EnableIf <has_write_some <this_layer_type,
|
||||
std::size_t (ConstBuffers const&, error_code&)>::value> ());
|
||||
}
|
||||
|
||||
template <typename ConstBufferSequence>
|
||||
std::size_t write_some (ConstBufferSequence const& buffers, error_code& ec,
|
||||
boost::true_type)
|
||||
{
|
||||
return m_object.write_some (buffers, ec);
|
||||
}
|
||||
|
||||
template <typename ConstBufferSequence>
|
||||
std::size_t write_some (ConstBufferSequence const&, error_code& ec,
|
||||
boost::false_type)
|
||||
{
|
||||
pure_virtual_called (__FILE__, __LINE__);
|
||||
ec = pure_virtual_error ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void async_read_some (MutableBuffers const& buffers, SharedHandlerPtr handler)
|
||||
{
|
||||
using namespace detail::SocketWrapperMemberChecks;
|
||||
async_read_some (buffers, BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler),
|
||||
EnableIf <has_async_read_some <this_layer_type,
|
||||
void (MutableBuffers const&, BOOST_ASIO_MOVE_ARG(SharedHandlerPtr))>::value> ());
|
||||
}
|
||||
|
||||
void async_read_some (MutableBuffers const& buffers,
|
||||
BOOST_ASIO_MOVE_ARG(SharedHandlerPtr) handler,
|
||||
boost::true_type)
|
||||
{
|
||||
m_object.async_read_some (buffers,
|
||||
BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler));
|
||||
}
|
||||
|
||||
void async_read_some (MutableBuffers const&,
|
||||
BOOST_ASIO_MOVE_ARG(SharedHandlerPtr) handler,
|
||||
boost::false_type)
|
||||
{
|
||||
get_io_service ().wrap (
|
||||
BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler))
|
||||
(pure_virtual_error (), 0);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void async_write_some (ConstBuffers const& buffers, SharedHandlerPtr handler)
|
||||
{
|
||||
using namespace detail::SocketWrapperMemberChecks;
|
||||
async_write_some (buffers, BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler),
|
||||
EnableIf <has_async_write_some <this_layer_type,
|
||||
void (ConstBuffers const&, BOOST_ASIO_MOVE_ARG(SharedHandlerPtr))>::value> ());
|
||||
}
|
||||
|
||||
void async_write_some (ConstBuffers const& buffers,
|
||||
BOOST_ASIO_MOVE_ARG(SharedHandlerPtr) handler,
|
||||
boost::true_type)
|
||||
{
|
||||
m_object.async_write_some (buffers,
|
||||
BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler));
|
||||
}
|
||||
|
||||
void async_write_some (ConstBuffers const&,
|
||||
BOOST_ASIO_MOVE_ARG(SharedHandlerPtr) handler,
|
||||
boost::false_type)
|
||||
{
|
||||
get_io_service ().wrap (
|
||||
BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler))
|
||||
(pure_virtual_error (), 0);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// ssl::stream
|
||||
//
|
||||
|
||||
template <class T>
|
||||
struct has_type_next_layer_type
|
||||
{
|
||||
typedef char yes;
|
||||
typedef struct {char dummy[2];} no;
|
||||
template <class C> static yes f(typename C::next_layer_type*);
|
||||
template <class C> static no f(...);
|
||||
#ifdef _MSC_VER
|
||||
static bool const value = sizeof(f<T>(0)) == 1;
|
||||
#else
|
||||
// This line fails to compile under Visual Studio 2012
|
||||
static bool const value = sizeof(has_type_next_layer_type<T>::f<T>(0)) == 1;
|
||||
#endif
|
||||
};
|
||||
|
||||
template <typename T, bool Exists = has_type_next_layer_type <T>::value >
|
||||
struct extract_next_layer_type
|
||||
{
|
||||
typedef typename T::next_layer_type type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct extract_next_layer_type <T, false>
|
||||
{
|
||||
typedef void type;
|
||||
};
|
||||
|
||||
// This will be void if next_layer_type doesn't exist in Object
|
||||
typedef typename extract_next_layer_type <this_layer_type>::type next_layer_type;
|
||||
|
||||
void* next_layer_ptr (char const* type_name) const
|
||||
{
|
||||
using namespace detail::SocketWrapperMemberChecks;
|
||||
return next_layer_ptr (type_name,
|
||||
EnableIf <has_type_next_layer_type <this_layer_type>::value> ());
|
||||
}
|
||||
|
||||
void* next_layer_ptr (char const* type_name,
|
||||
boost::true_type) const
|
||||
{
|
||||
char const* const name (typeid (typename this_layer_type::next_layer_type).name ());
|
||||
if (strcmp (name, type_name) == 0)
|
||||
return const_cast <void*> (static_cast <void const*> (&m_object.next_layer ()));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void* next_layer_ptr (char const*,
|
||||
boost::false_type) const
|
||||
{
|
||||
pure_virtual_called (__FILE__, __LINE__);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
bool needs_handshake ()
|
||||
{
|
||||
using namespace detail::SocketWrapperMemberChecks;
|
||||
return
|
||||
has_handshake <this_layer_type,
|
||||
error_code (handshake_type, error_code&)>::value ||
|
||||
has_async_handshake <this_layer_type,
|
||||
void (handshake_type, BOOST_ASIO_MOVE_ARG(SharedHandlerPtr))>::value;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void set_verify_mode (int verify_mode)
|
||||
{
|
||||
using namespace detail::SocketWrapperMemberChecks;
|
||||
set_verify_mode (verify_mode,
|
||||
EnableIf <has_set_verify_mode <this_layer_type,
|
||||
void (int)>::value> ());
|
||||
|
||||
}
|
||||
|
||||
void set_verify_mode (int verify_mode,
|
||||
boost::true_type)
|
||||
{
|
||||
m_object.set_verify_mode (verify_mode);
|
||||
}
|
||||
|
||||
void set_verify_mode (int,
|
||||
boost::false_type)
|
||||
{
|
||||
pure_virtual_called (__FILE__, __LINE__);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
error_code handshake (handshake_type type, error_code& ec)
|
||||
{
|
||||
using namespace detail::SocketWrapperMemberChecks;
|
||||
return handshake (type, ec,
|
||||
EnableIf <has_handshake <this_layer_type,
|
||||
error_code (handshake_type, error_code&)>::value> ());
|
||||
}
|
||||
|
||||
error_code handshake (handshake_type type, error_code& ec,
|
||||
boost::true_type)
|
||||
{
|
||||
return m_object.handshake (type, ec);
|
||||
}
|
||||
|
||||
error_code handshake (handshake_type, error_code& ec,
|
||||
boost::false_type)
|
||||
{
|
||||
return pure_virtual_error (ec, __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void async_handshake (handshake_type type, SharedHandlerPtr handler)
|
||||
{
|
||||
using namespace detail::SocketWrapperMemberChecks;
|
||||
async_handshake (type, BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler),
|
||||
EnableIf <has_async_handshake <this_layer_type,
|
||||
void (handshake_type, BOOST_ASIO_MOVE_ARG(SharedHandlerPtr))>::value> ());
|
||||
}
|
||||
|
||||
void async_handshake (handshake_type type,
|
||||
BOOST_ASIO_MOVE_ARG(SharedHandlerPtr) handler,
|
||||
boost::true_type)
|
||||
{
|
||||
m_object.async_handshake (type,
|
||||
BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler));
|
||||
}
|
||||
|
||||
void async_handshake (handshake_type, BOOST_ASIO_MOVE_ARG(SharedHandlerPtr) handler,
|
||||
boost::false_type)
|
||||
{
|
||||
get_io_service ().wrap (
|
||||
BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler))
|
||||
(pure_virtual_error ());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
#if BEAST_ASIO_HAS_BUFFEREDHANDSHAKE
|
||||
|
||||
error_code handshake (handshake_type type,
|
||||
ConstBuffers const& buffers, error_code& ec)
|
||||
{
|
||||
using namespace detail::SocketWrapperMemberChecks;
|
||||
return handshake (type, buffers, ec,
|
||||
EnableIf <has_handshake <this_layer_type,
|
||||
error_code (handshake_type, ConstBuffers const&, error_code&)>::value> ());
|
||||
}
|
||||
|
||||
error_code handshake (handshake_type type,
|
||||
ConstBuffers const& buffers, error_code& ec,
|
||||
boost::true_type)
|
||||
{
|
||||
return m_object.handshake (type, buffers, ec);
|
||||
}
|
||||
|
||||
error_code handshake (handshake_type, ConstBuffers const&, error_code& ec,
|
||||
boost::false_type)
|
||||
{
|
||||
return pure_virtual_error (ec, __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void async_handshake (handshake_type type,
|
||||
ConstBuffers const& buffers, SharedHandlerPtr handler)
|
||||
{
|
||||
using namespace detail::SocketWrapperMemberChecks;
|
||||
async_handshake (type, buffers,
|
||||
BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler),
|
||||
EnableIf <has_async_handshake <this_layer_type,
|
||||
void (handshake_type, ConstBuffers const&,
|
||||
BOOST_ASIO_MOVE_ARG(SharedHandlerPtr))>::value> ());
|
||||
}
|
||||
|
||||
void async_handshake (handshake_type type, ConstBuffers const& buffers,
|
||||
BOOST_ASIO_MOVE_ARG(SharedHandlerPtr) handler,
|
||||
boost::true_type)
|
||||
{
|
||||
m_object.async_handshake (type, buffers,
|
||||
BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler));
|
||||
}
|
||||
|
||||
void async_handshake (handshake_type, ConstBuffers const&,
|
||||
BOOST_ASIO_MOVE_ARG(SharedHandlerPtr) handler,
|
||||
boost::false_type)
|
||||
{
|
||||
get_io_service ().wrap (
|
||||
BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler))
|
||||
(pure_virtual_error (), 0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
error_code shutdown (error_code& ec)
|
||||
{
|
||||
using namespace detail::SocketWrapperMemberChecks;
|
||||
return shutdown (ec,
|
||||
EnableIf <has_shutdown <this_layer_type,
|
||||
error_code (error_code&)>::value> ());
|
||||
}
|
||||
|
||||
error_code shutdown (error_code& ec,
|
||||
boost::true_type)
|
||||
{
|
||||
return m_object.shutdown (ec);
|
||||
}
|
||||
|
||||
error_code shutdown (error_code& ec,
|
||||
boost::false_type)
|
||||
{
|
||||
return pure_virtual_error (ec, __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void async_shutdown (SharedHandlerPtr handler)
|
||||
{
|
||||
using namespace detail::SocketWrapperMemberChecks;
|
||||
async_shutdown (BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler),
|
||||
EnableIf <has_async_shutdown <this_layer_type,
|
||||
void (BOOST_ASIO_MOVE_ARG(SharedHandlerPtr))>::value> ());
|
||||
}
|
||||
|
||||
void async_shutdown (BOOST_ASIO_MOVE_ARG(SharedHandlerPtr) handler,
|
||||
boost::true_type)
|
||||
{
|
||||
m_object.async_shutdown (
|
||||
BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler));
|
||||
}
|
||||
|
||||
void async_shutdown (BOOST_ASIO_MOVE_ARG(SharedHandlerPtr) handler,
|
||||
boost::false_type)
|
||||
{
|
||||
get_io_service ().wrap (
|
||||
BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler))
|
||||
(pure_virtual_error ());
|
||||
}
|
||||
|
||||
private:
|
||||
Object m_object;
|
||||
};
|
||||
|
||||
#endif
|
||||
66
modules/beast_asio/sockets/SocketWrapperStrand.h
Normal file
66
modules/beast_asio/sockets/SocketWrapperStrand.h
Normal file
@@ -0,0 +1,66 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_SOCKETS_SOCKETWRAPPERSTRAND_H_INCLUDED
|
||||
#define BEAST_ASIO_SOCKETS_SOCKETWRAPPERSTRAND_H_INCLUDED
|
||||
|
||||
/** Wraps the async I/O of a SocketWrapper with an io_service::strand
|
||||
To use this in a chain of wrappers, customize the Base type.
|
||||
*/
|
||||
template <typename Object, typename Base = SocketWrapper <Object> >
|
||||
class SocketWrapperStrand
|
||||
: public Base
|
||||
{
|
||||
public:
|
||||
template <typename Arg>
|
||||
SocketWrapperStrand (Arg& arg)
|
||||
: Base (arg)
|
||||
, m_strand (this->get_io_service ())
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Arg1, typename Arg2>
|
||||
SocketWrapperStrand (Arg1& arg1, Arg2& arg2)
|
||||
: Base (arg1, arg2)
|
||||
, m_strand (this->get_io_service ())
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// basic_stream_socket
|
||||
//
|
||||
|
||||
void async_read_some (MutableBuffers const& buffers, SharedHandlerPtr handler)
|
||||
{
|
||||
this->Base::async_read_some (buffers,
|
||||
newReadHandler (m_strand.wrap (handler)));
|
||||
}
|
||||
|
||||
void async_write_some (MutableBuffers const& buffers, SharedHandlerPtr handler)
|
||||
{
|
||||
this->Base::async_write_some (buffers,
|
||||
newWriteHandler (m_strand.wrap (handler)));
|
||||
}
|
||||
|
||||
protected:
|
||||
boost::asio::io_service::strand m_strand;
|
||||
};
|
||||
|
||||
#endif
|
||||
81
modules/beast_asio/system/BoostIncludes.h
Normal file
81
modules/beast_asio/system/BoostIncludes.h
Normal file
@@ -0,0 +1,81 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_SYSTEM_BOOSTINCLUDES_H_INCLUDED
|
||||
#define BEAST_ASIO_SYSTEM_BOOSTINCLUDES_H_INCLUDED
|
||||
|
||||
// Make sure we take care of fixing boost::bind oddities first.
|
||||
#if !defined(BEAST_CORE_H_INCLUDED)
|
||||
#error beast_core.h must be included before including this file
|
||||
#endif
|
||||
|
||||
// These should have already been set in your project, but
|
||||
// if you forgot then we will be optimistic and choose the latest.
|
||||
//
|
||||
#if BEAST_WIN32
|
||||
# ifndef _WIN32_WINNT
|
||||
# pragma message ("Warning: _WIN32_WINNT was not set in your project")
|
||||
# define _WIN32_WINNT 0x0600
|
||||
# endif
|
||||
# ifndef _VARIADIC_MAX
|
||||
# define _VARIADIC_MAX 10
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// Unfortunately, we use some boost detail elements
|
||||
//
|
||||
// https://svn.boost.org/trac/boost/ticket/9024
|
||||
|
||||
#include <boost/version.hpp>
|
||||
#include <boost/array.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/asio/ssl.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/type_traits.hpp>
|
||||
#include <boost/asio/detail/handler_alloc_helpers.hpp>
|
||||
#include <boost/asio/detail/handler_invoke_helpers.hpp>
|
||||
|
||||
// Continuation hooks added in 1.54.0
|
||||
#ifndef BEAST_ASIO_HAS_CONTINUATION_HOOKS
|
||||
# if BOOST_VERSION >= 105400
|
||||
# define BEAST_ASIO_HAS_CONTINUATION_HOOKS 1
|
||||
# else
|
||||
# define BEAST_ASIO_HAS_CONTINUATION_HOOKS 0
|
||||
# endif
|
||||
#endif
|
||||
#if BEAST_ASIO_HAS_CONTINUATION_HOOKS
|
||||
# include <boost/asio/detail/handler_cont_helpers.hpp>
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Configure some options based on the version of boost
|
||||
#if BOOST_VERSION >= 105400
|
||||
# ifndef BEAST_ASIO_HAS_BUFFEREDHANDSHAKE
|
||||
# define BEAST_ASIO_HAS_BUFFEREDHANDSHAKE 1
|
||||
# endif
|
||||
#else
|
||||
# ifndef BEAST_ASIO_HAS_BUFFEREDHANDSHAKE
|
||||
# define BEAST_ASIO_HAS_BUFFEREDHANDSHAKE 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
82
modules/beast_asio/system/BoostUnitTests.cpp
Normal file
82
modules/beast_asio/system/BoostUnitTests.cpp
Normal file
@@ -0,0 +1,82 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
/** Test for showing information about the build of boost.
|
||||
*/
|
||||
class BoostUnitTests : public UnitTest
|
||||
{
|
||||
public:
|
||||
struct BoostVersion
|
||||
{
|
||||
explicit BoostVersion (int value)
|
||||
: vmajor (value / 100000)
|
||||
, vminor ((value / 100) % 100)
|
||||
, vpatch (value % 100)
|
||||
{
|
||||
}
|
||||
|
||||
String toString () const noexcept
|
||||
{
|
||||
return String (vmajor) + "." +
|
||||
String (vminor).paddedLeft ('0', 2) + "." +
|
||||
String (vpatch).paddedLeft ('0', 2);
|
||||
}
|
||||
|
||||
int vmajor;
|
||||
int vminor;
|
||||
int vpatch;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
minimumVersion = 104700
|
||||
};
|
||||
|
||||
// To prevent constant conditional expression warning
|
||||
static int getMinimumVersion ()
|
||||
{
|
||||
return minimumVersion;
|
||||
}
|
||||
|
||||
void runTest ()
|
||||
{
|
||||
beginTestCase ("version");
|
||||
|
||||
BoostVersion version (BOOST_VERSION);
|
||||
|
||||
logMessage (String ("BOOST_VERSION = " + version.toString ()));
|
||||
logMessage (String ("BOOST_LIB_VERSION = '") + BOOST_LIB_VERSION + "'");
|
||||
|
||||
if (BOOST_VERSION >= getMinimumVersion ())
|
||||
{
|
||||
pass ();
|
||||
}
|
||||
else
|
||||
{
|
||||
fail (String ("Boost version is below ") +
|
||||
BoostVersion (minimumVersion).toString ());
|
||||
}
|
||||
}
|
||||
|
||||
BoostUnitTests () : UnitTest ("boost", "beast")
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
static BoostUnitTests boostUnitTests;
|
||||
40
modules/beast_asio/system/OpenSSLIncludes.h
Normal file
40
modules/beast_asio/system/OpenSSLIncludes.h
Normal file
@@ -0,0 +1,40 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_SYSTEM_OPENSSLINCLUDES_H_INCLUDED
|
||||
#define BEAST_ASIO_SYSTEM_OPENSSLINCLUDES_H_INCLUDED
|
||||
|
||||
#define OPENSSL_THREAD_DEFINES
|
||||
#include <openssl/opensslconf.h>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Configure our settings based on what we find
|
||||
//
|
||||
#if defined(OPENSSL_THREADS)
|
||||
# ifndef BEAST_OPENSSL_MULTITHREADED
|
||||
# define BEAST_OPENSSL_MULTITHREADED 1
|
||||
# endif
|
||||
#else
|
||||
# ifndef BEAST_OPENSSL_MULTITHREADED
|
||||
# define BEAST_OPENSSL_MULTITHREADED 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
100
modules/beast_asio/tests/PeerTest.cpp
Normal file
100
modules/beast_asio/tests/PeerTest.cpp
Normal file
@@ -0,0 +1,100 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
PeerTest::Result::Result ()
|
||||
: m_ec (TestPeerBasics::make_error (TestPeerBasics::errc::skipped))
|
||||
, m_message (m_ec.message ())
|
||||
{
|
||||
}
|
||||
|
||||
PeerTest::Result::Result (boost::system::error_code const& ec, String const& prefix)
|
||||
: m_ec (ec)
|
||||
, m_message ((prefix == String::empty) ? ec.message ()
|
||||
: prefix + ": " + ec.message ())
|
||||
{
|
||||
}
|
||||
|
||||
PeerTest::Result::Result (std::exception const& e, String const& prefix)
|
||||
: m_ec (TestPeerBasics::make_error (TestPeerBasics::errc::exceptioned))
|
||||
, m_message ((prefix == String::empty) ? e.what ()
|
||||
: prefix + ": " + e.what ())
|
||||
{
|
||||
}
|
||||
|
||||
bool PeerTest::Result::operator== (Result const& other) const noexcept
|
||||
{
|
||||
return m_ec == other.m_ec;
|
||||
}
|
||||
|
||||
bool PeerTest::Result::operator!= (Result const& other) const noexcept
|
||||
{
|
||||
return m_ec != other.m_ec;
|
||||
}
|
||||
|
||||
bool PeerTest::Result::failed () const noexcept
|
||||
{
|
||||
return TestPeerBasics::failure (m_ec);
|
||||
}
|
||||
|
||||
bool PeerTest::Result::timedout () const noexcept
|
||||
{
|
||||
return m_ec == TestPeerBasics::make_error (TestPeerBasics::errc::timeout);
|
||||
}
|
||||
|
||||
String PeerTest::Result::message () const noexcept
|
||||
{
|
||||
return m_message;
|
||||
}
|
||||
|
||||
bool PeerTest::Result::report (UnitTest& test, bool reportPassingTests) const
|
||||
{
|
||||
bool const success = test.unexpected (failed (), message ());
|
||||
if (reportPassingTests && success)
|
||||
test.logMessage (String ("pass ") + message());
|
||||
return success;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
PeerTest::Results::Results ()
|
||||
: name ("unknown")
|
||||
{
|
||||
}
|
||||
|
||||
bool PeerTest::Results::operator== (Results const& other) const noexcept
|
||||
{
|
||||
return (client == other.client) && (server == other.server);
|
||||
}
|
||||
|
||||
bool PeerTest::Results::operator!= (Results const& other) const noexcept
|
||||
{
|
||||
return (client != other.client) || (server != other.server);
|
||||
}
|
||||
|
||||
bool PeerTest::Results::report (UnitTest& test, bool beginTestCase) const
|
||||
{
|
||||
if (beginTestCase)
|
||||
test.beginTestCase (name);
|
||||
bool success = true;
|
||||
if (! client.report (test))
|
||||
success = false;
|
||||
if (! server.report (test))
|
||||
success = false;
|
||||
return success;
|
||||
}
|
||||
239
modules/beast_asio/tests/PeerTest.h
Normal file
239
modules/beast_asio/tests/PeerTest.h
Normal file
@@ -0,0 +1,239 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_TESTS_PEERTEST_H_INCLUDED
|
||||
#define BEAST_ASIO_TESTS_PEERTEST_H_INCLUDED
|
||||
|
||||
/** Performs a test of two peers defined by template parameters.
|
||||
*/
|
||||
class PeerTest
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
/** How long to wait before aborting a peer and reporting a timeout.
|
||||
|
||||
@note Aborting synchronous logics may cause undefined behavior.
|
||||
*/
|
||||
defaultTimeoutSeconds = 30
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/** Holds the test results for one peer.
|
||||
*/
|
||||
class Result
|
||||
{
|
||||
public:
|
||||
/** Default constructor indicates the test was skipped.
|
||||
*/
|
||||
Result ();
|
||||
|
||||
/** Construct from an error code.
|
||||
The prefix is prepended to the error message.
|
||||
*/
|
||||
explicit Result (boost::system::error_code const& ec, String const& prefix = "");
|
||||
explicit Result (std::exception const& e, String const& prefix = "");
|
||||
|
||||
/** Returns true if the error codes match (message is ignored).
|
||||
*/
|
||||
bool operator== (Result const& other) const noexcept;
|
||||
bool operator!= (Result const& other) const noexcept;
|
||||
|
||||
/** Returns true if the peer failed.
|
||||
*/
|
||||
bool failed () const noexcept;
|
||||
|
||||
/** Convenience for determining if the peer timed out.
|
||||
*/
|
||||
bool timedout () const noexcept;
|
||||
|
||||
/** Provides a descriptive message.
|
||||
This is suitable to pass to UnitTest::fail.
|
||||
*/
|
||||
String message () const noexcept;
|
||||
|
||||
/** Report the result to a UnitTest object.
|
||||
A return value of true indicates success.
|
||||
*/
|
||||
bool report (UnitTest& test, bool reportPassingTests = false) const;
|
||||
|
||||
private:
|
||||
boost::system::error_code m_ec;
|
||||
String m_message;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/** Holds the results for both peers in a test.
|
||||
*/
|
||||
struct Results
|
||||
{
|
||||
String name; // A descriptive name for this test case.
|
||||
Result client;
|
||||
Result server;
|
||||
|
||||
Results ();
|
||||
|
||||
/** Determines if client and server results match. */
|
||||
bool operator== (Results const& other) const noexcept;
|
||||
bool operator!= (Results const& other) const noexcept;
|
||||
|
||||
/** Report the results to a UnitTest object.
|
||||
A return value of true indicates success.
|
||||
@param beginTestCase `true` to call test.beginTestCase for you
|
||||
*/
|
||||
bool report (UnitTest& test, bool beginTestCase = true) const;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/** Test two peers and return the results.
|
||||
*/
|
||||
template <typename Details, typename ClientLogic, typename ServerLogic, typename ClientArg, typename ServerArg>
|
||||
static Results run (ClientArg const& clientArg, ServerArg const& serverArg, int timeoutSeconds = defaultTimeoutSeconds)
|
||||
{
|
||||
Results results;
|
||||
|
||||
if (Process::isRunningUnderDebugger ())
|
||||
timeoutSeconds = -1;
|
||||
|
||||
try
|
||||
{
|
||||
TestPeerType <ServerLogic, Details> server (serverArg);
|
||||
|
||||
results.name = server.name () + Details::getArgName (serverArg);
|
||||
|
||||
try
|
||||
{
|
||||
TestPeerType <ClientLogic, Details> client (clientArg);
|
||||
|
||||
results.name << " / " + client.name () + Details::getArgName (clientArg);
|
||||
|
||||
try
|
||||
{
|
||||
server.start (timeoutSeconds);
|
||||
|
||||
try
|
||||
{
|
||||
client.start (timeoutSeconds);
|
||||
|
||||
boost::system::error_code const ec = client.join ();
|
||||
|
||||
results.client = Result (ec, client.name ());
|
||||
|
||||
try
|
||||
{
|
||||
boost::system::error_code const ec = server.join ();
|
||||
|
||||
results.server = Result (ec, server.name ());
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
results.server = Result (e, server.name ());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
results.server = Result (TestPeerBasics::make_error (
|
||||
TestPeerBasics::errc::exceptioned), server.name ());
|
||||
}
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
results.server = Result (e, client.name ());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
results.client = Result (TestPeerBasics::make_error (
|
||||
TestPeerBasics::errc::exceptioned), client.name ());
|
||||
}
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
results.server = Result (e, server.name ());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
results.server = Result (TestPeerBasics::make_error (
|
||||
TestPeerBasics::errc::exceptioned), server.name ());
|
||||
}
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
results.server = Result (e, "client");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
results.client = Result (TestPeerBasics::make_error (
|
||||
TestPeerBasics::errc::exceptioned), "client");
|
||||
}
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
results.server = Result (e, "server");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
results.server = Result (TestPeerBasics::make_error (
|
||||
TestPeerBasics::errc::exceptioned), "server");
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
template <typename Details, typename ClientLogic, typename ServerLogic, class Arg>
|
||||
static Results run (Arg const& arg, int timeoutSeconds = defaultTimeoutSeconds)
|
||||
{
|
||||
return run <Details, ClientLogic, ServerLogic, Arg, Arg> (arg, arg, timeoutSeconds);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/** Reports tests of Details for all known asynchronous logic combinations to a UnitTest.
|
||||
*/
|
||||
template <typename Details, class Arg>
|
||||
static void report_async (UnitTest& test, Arg const& arg,
|
||||
int timeoutSeconds = defaultTimeoutSeconds,
|
||||
bool beginTestCase = true)
|
||||
{
|
||||
run <Details, TestPeerLogicAsyncClient, TestPeerLogicAsyncServer>
|
||||
(arg, timeoutSeconds).report (test, beginTestCase);
|
||||
}
|
||||
|
||||
/** Reports tests of Details against all known logic combinations to a UnitTest.
|
||||
*/
|
||||
template <typename Details, class Arg>
|
||||
static void report (UnitTest& test, Arg const& arg,
|
||||
int timeoutSeconds = defaultTimeoutSeconds,
|
||||
bool beginTestCase = true)
|
||||
{
|
||||
run <Details, TestPeerLogicSyncClient, TestPeerLogicSyncServer>
|
||||
(arg, timeoutSeconds).report (test, beginTestCase);
|
||||
|
||||
run <Details, TestPeerLogicAsyncClient, TestPeerLogicSyncServer>
|
||||
(arg, timeoutSeconds).report (test, beginTestCase);
|
||||
|
||||
run <Details, TestPeerLogicSyncClient, TestPeerLogicAsyncServer>
|
||||
(arg, timeoutSeconds).report (test, beginTestCase);
|
||||
|
||||
report_async <Details> (test, arg, timeoutSeconds, beginTestCase);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
53
modules/beast_asio/tests/TestPeer.h
Normal file
53
modules/beast_asio/tests/TestPeer.h
Normal file
@@ -0,0 +1,53 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_TESTS_TESTPEER_H_INCLUDED
|
||||
#define BEAST_ASIO_TESTS_TESTPEER_H_INCLUDED
|
||||
|
||||
/** An abstract peer for unit tests.
|
||||
*/
|
||||
class TestPeer : public TestPeerBasics
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
// This should be long enough to go about your business.
|
||||
defaultTimeout = 10
|
||||
};
|
||||
|
||||
virtual ~TestPeer () { }
|
||||
|
||||
/** Get the name of this peer. */
|
||||
virtual String name () const = 0;
|
||||
|
||||
/** Start the peer.
|
||||
If timeoutSeconds is 0 or less, the wait is infinite.
|
||||
@param timeoutSeconds How long until the peer should be
|
||||
considered timed out.
|
||||
*/
|
||||
virtual void start (int timeoutSeconds = defaultTimeout) = 0;
|
||||
|
||||
/** Wait for the peer to finish.
|
||||
|
||||
@return Any error code generated during the server operation.
|
||||
*/
|
||||
virtual boost::system::error_code join () = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
155
modules/beast_asio/tests/TestPeerBasics.cpp
Normal file
155
modules/beast_asio/tests/TestPeerBasics.cpp
Normal file
@@ -0,0 +1,155 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
TestPeerBasics::Model::Model (model_t model)
|
||||
: m_model (model)
|
||||
{
|
||||
}
|
||||
|
||||
String TestPeerBasics::Model::name () const noexcept
|
||||
{
|
||||
if (m_model == async)
|
||||
return "async";
|
||||
return "sync";
|
||||
}
|
||||
|
||||
bool TestPeerBasics::Model::operator== (model_t model) const noexcept
|
||||
{
|
||||
return m_model == model;
|
||||
}
|
||||
|
||||
boost::asio::ssl::stream_base::handshake_type
|
||||
TestPeerBasics::to_handshake_type (PeerRole const& role)
|
||||
{
|
||||
if (role == PeerRole::client)
|
||||
return boost::asio::ssl::stream_base::client;
|
||||
return boost::asio::ssl::stream_base::server;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
boost::system::error_category const& TestPeerBasics::test_category () noexcept
|
||||
{
|
||||
struct test_category_type : boost::system::error_category
|
||||
{
|
||||
char const* name () const noexcept
|
||||
{
|
||||
return "TestPeer";
|
||||
}
|
||||
|
||||
std::string message (int ev) const
|
||||
{
|
||||
switch (ev)
|
||||
{
|
||||
case errc::none: return "No error";
|
||||
case errc::timeout: return "The timeout expired before the test could complete";
|
||||
case errc::unexpected: return "An unexpected test result was encountered";
|
||||
case errc::exceptioned: return "An unexpected exception was thrown";
|
||||
case errc::skipped: return "The test was skipped because of previous errors";
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
return "An unknown error";
|
||||
}
|
||||
|
||||
boost::system::error_condition default_error_condition (int ev) const noexcept
|
||||
{
|
||||
return boost::system::error_condition (ev, *this);
|
||||
}
|
||||
|
||||
bool equivalent (int ev, boost::system::error_condition const& condition) const noexcept
|
||||
{
|
||||
return default_error_condition (ev) == condition;
|
||||
}
|
||||
|
||||
bool equivalent (boost::system::error_code const& code, int ev) const noexcept
|
||||
{
|
||||
return *this == code.category() && code.value() == ev;
|
||||
}
|
||||
};
|
||||
|
||||
static test_category_type category;
|
||||
|
||||
return category;
|
||||
}
|
||||
|
||||
boost::system::error_code TestPeerBasics::make_error (errc::errc_t ev) noexcept
|
||||
{
|
||||
return boost::system::error_code (ev, test_category ());
|
||||
}
|
||||
|
||||
boost::system::error_code TestPeerBasics::make_error (errc::errc_t ev, boost::system::error_code& ec) noexcept
|
||||
{
|
||||
return ec = make_error (ev);
|
||||
}
|
||||
|
||||
bool TestPeerBasics::success (boost::system::error_code const& ec, bool eofIsOkay) noexcept
|
||||
{
|
||||
if (eofIsOkay && ec == boost::asio::error::eof)
|
||||
return true;
|
||||
if (! ec)
|
||||
return true;
|
||||
breakpoint (ec);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TestPeerBasics::failure (boost::system::error_code const& ec, bool eofIsOkay) noexcept
|
||||
{
|
||||
return ! success (ec, eofIsOkay);
|
||||
}
|
||||
|
||||
bool TestPeerBasics::expected (bool condition, boost::system::error_code& ec) noexcept
|
||||
{
|
||||
if (condition)
|
||||
{
|
||||
ec = boost::system::error_code ();
|
||||
}
|
||||
else
|
||||
{
|
||||
make_error (errc::unexpected, ec);
|
||||
breakpoint (ec);
|
||||
}
|
||||
return condition;
|
||||
}
|
||||
|
||||
bool TestPeerBasics::unexpected (bool condition, boost::system::error_code& ec) noexcept
|
||||
{
|
||||
return ! expected (condition, ec);
|
||||
}
|
||||
|
||||
bool TestPeerBasics::aborted (boost::system::error_code const& ec) noexcept
|
||||
{
|
||||
return ec == boost::asio::error::operation_aborted;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void TestPeerBasics::breakpoint (boost::system::error_code const& ec)
|
||||
{
|
||||
// Set a breakpoint here to catch a failure
|
||||
std::string const& message = ec.message ();
|
||||
char const* const c_str = message.c_str ();
|
||||
|
||||
breakpoint (c_str);
|
||||
}
|
||||
|
||||
void TestPeerBasics::breakpoint (char const* const)
|
||||
{
|
||||
}
|
||||
106
modules/beast_asio/tests/TestPeerBasics.h
Normal file
106
modules/beast_asio/tests/TestPeerBasics.h
Normal file
@@ -0,0 +1,106 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_TESTS_TESTPEERBASICS_H_INCLUDED
|
||||
#define BEAST_ASIO_TESTS_TESTPEERBASICS_H_INCLUDED
|
||||
|
||||
/** Common declarations for TestPeer.
|
||||
|
||||
@see TestPeer
|
||||
*/
|
||||
class TestPeerBasics
|
||||
{
|
||||
public:
|
||||
/** Selects between synchronous or asynchronous networking i/o usage. */
|
||||
struct Model
|
||||
{
|
||||
enum model_t
|
||||
{
|
||||
sync,
|
||||
async
|
||||
};
|
||||
|
||||
Model (model_t model);
|
||||
String name () const noexcept;
|
||||
bool operator== (model_t model) const noexcept;
|
||||
|
||||
private:
|
||||
model_t m_model;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/** Convert a PeerRole to boost::asio::ssl::stream_base_handshake_type */
|
||||
static boost::asio::ssl::stream_base::handshake_type to_handshake_type (PeerRole const& role);
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
// Custom error codes for distinguishing test conditions
|
||||
struct errc
|
||||
{
|
||||
enum errc_t
|
||||
{
|
||||
none = 0,
|
||||
timeout, // The peer join timeout expired
|
||||
unexpected, // An expected condition was false
|
||||
exceptioned, // An exception occurred
|
||||
skipped // Test skipped due to previous errors
|
||||
};
|
||||
};
|
||||
|
||||
/** Returns the category that represents TestPeer errors.
|
||||
*/
|
||||
static boost::system::error_category const& test_category () noexcept;
|
||||
|
||||
/** Creates a test error_code from the give code value.
|
||||
*/
|
||||
static boost::system::error_code make_error (errc::errc_t ev) noexcept;
|
||||
|
||||
/** Sets the passed error_code to a test error and returns it.
|
||||
*/
|
||||
static boost::system::error_code make_error (errc::errc_t ev,
|
||||
boost::system::error_code& ec) noexcept;
|
||||
|
||||
/** Returns true if the error code indicates success.
|
||||
*/
|
||||
static bool success (boost::system::error_code const& ec, bool eofIsOkay = false) noexcept;
|
||||
|
||||
/** Returns false if the error code indicates failure.
|
||||
*/
|
||||
static bool failure (boost::system::error_code const& ec, bool eofIsOkay = false) noexcept;
|
||||
|
||||
/** Set the error based on a failed condition and return the success.
|
||||
*/
|
||||
static bool expected (bool condition, boost::system::error_code& ec) noexcept;
|
||||
|
||||
/** Set the error based on a passed condition and return the success.
|
||||
*/
|
||||
static bool unexpected (bool condition, boost::system::error_code& ec) noexcept;
|
||||
|
||||
/** Returns true if the error condition indicates an aborted I/O. */
|
||||
static bool aborted (boost::system::error_code const& ec) noexcept;
|
||||
|
||||
/** Provides a place to set a breakpoint to catch a failed condition. */
|
||||
static void breakpoint (boost::system::error_code const& ec);
|
||||
|
||||
/** Forces the variable to exist in the debugger. */
|
||||
static void breakpoint (char const* const message);
|
||||
};
|
||||
|
||||
#endif
|
||||
45
modules/beast_asio/tests/TestPeerDetails.h
Normal file
45
modules/beast_asio/tests/TestPeerDetails.h
Normal file
@@ -0,0 +1,45 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_TESTS_TESTPEERDETAILS_H_INCLUDED
|
||||
#define BEAST_ASIO_TESTS_TESTPEERDETAILS_H_INCLUDED
|
||||
|
||||
/** Base class of all detail objects.
|
||||
*/
|
||||
class TestPeerDetails
|
||||
{
|
||||
public:
|
||||
virtual ~TestPeerDetails () { }
|
||||
|
||||
virtual String name () = 0;
|
||||
|
||||
virtual Socket& get_socket () = 0;
|
||||
|
||||
virtual Socket& get_acceptor () = 0;
|
||||
|
||||
boost::asio::io_service& get_io_service ()
|
||||
{
|
||||
return m_io_service;
|
||||
}
|
||||
|
||||
private:
|
||||
boost::asio::io_service m_io_service;
|
||||
};
|
||||
|
||||
#endif
|
||||
108
modules/beast_asio/tests/TestPeerDetailsTcp.h
Normal file
108
modules/beast_asio/tests/TestPeerDetailsTcp.h
Normal file
@@ -0,0 +1,108 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_TESTS_TESTPEERDETAILSTCP_H_INCLUDED
|
||||
#define BEAST_ASIO_TESTS_TESTPEERDETAILSTCP_H_INCLUDED
|
||||
|
||||
/** Some predefined Detail classes for TestPeer
|
||||
*/
|
||||
struct TcpDetails : public TestPeerDetails
|
||||
{
|
||||
protected:
|
||||
typedef boost::asio::ip::tcp protocol_type;
|
||||
typedef protocol_type::socket socket_type;
|
||||
typedef protocol_type::acceptor acceptor_type;
|
||||
typedef protocol_type::endpoint endpoint_type;
|
||||
typedef protocol_type::resolver resolver_type;
|
||||
|
||||
public:
|
||||
typedef protocol_type arg_type;
|
||||
typedef socket_type native_socket_type;
|
||||
typedef acceptor_type native_acceptor_type;
|
||||
|
||||
explicit TcpDetails (arg_type protocol)
|
||||
: m_protocol (protocol)
|
||||
, m_socket (get_io_service ())
|
||||
, m_acceptor (get_io_service ())
|
||||
, m_socket_wrapper (m_socket)
|
||||
, m_acceptor_wrapper (m_acceptor)
|
||||
{
|
||||
}
|
||||
|
||||
static String getArgName (arg_type arg)
|
||||
{
|
||||
if (arg == protocol_type::v4 ())
|
||||
return ".tcpv4";
|
||||
else if (arg == protocol_type::v6 ())
|
||||
return ".tcpv6";
|
||||
return ".tcp?";
|
||||
}
|
||||
|
||||
String name ()
|
||||
{
|
||||
return getArgName (m_protocol);
|
||||
}
|
||||
|
||||
Socket& get_socket ()
|
||||
{
|
||||
return m_socket_wrapper;
|
||||
}
|
||||
|
||||
Socket& get_acceptor ()
|
||||
{
|
||||
return m_acceptor_wrapper;
|
||||
}
|
||||
|
||||
socket_type& get_native_socket ()
|
||||
{
|
||||
return m_socket;
|
||||
}
|
||||
|
||||
acceptor_type& get_native_acceptor ()
|
||||
{
|
||||
return m_acceptor;
|
||||
}
|
||||
|
||||
endpoint_type get_endpoint (PeerRole role)
|
||||
{
|
||||
if (m_protocol == protocol_type::v4 ())
|
||||
{
|
||||
if (role == PeerRole::server)
|
||||
return endpoint_type (m_protocol, 1053);
|
||||
else
|
||||
return endpoint_type (boost::asio::ip::address_v4::loopback (), 1053);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (role == PeerRole::server)
|
||||
return endpoint_type (m_protocol, 1052);
|
||||
else
|
||||
return endpoint_type (boost::asio::ip::address_v6 ().from_string ("::1"), 1052);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
protocol_type m_protocol;
|
||||
socket_type m_socket;
|
||||
acceptor_type m_acceptor;
|
||||
SocketWrapper <socket_type&> m_socket_wrapper;
|
||||
SocketWrapper <acceptor_type&> m_acceptor_wrapper;
|
||||
};
|
||||
|
||||
#endif
|
||||
63
modules/beast_asio/tests/TestPeerLogic.cpp
Normal file
63
modules/beast_asio/tests/TestPeerLogic.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
TestPeerLogic::TestPeerLogic (Socket& socket)
|
||||
: m_socket (&socket)
|
||||
{
|
||||
}
|
||||
|
||||
TestPeerLogic::error_code& TestPeerLogic::error () noexcept
|
||||
{
|
||||
return m_ec;
|
||||
}
|
||||
|
||||
TestPeerLogic::error_code const& TestPeerLogic::error () const noexcept
|
||||
{
|
||||
return m_ec;
|
||||
}
|
||||
|
||||
TestPeerLogic::error_code const& TestPeerLogic::error (error_code const& ec) noexcept
|
||||
{
|
||||
return m_ec = ec;
|
||||
}
|
||||
|
||||
Socket& TestPeerLogic::socket () noexcept
|
||||
{
|
||||
return *m_socket;
|
||||
}
|
||||
|
||||
void TestPeerLogic::on_connect ()
|
||||
{
|
||||
pure_virtual ();
|
||||
}
|
||||
|
||||
void TestPeerLogic::on_connect_async (error_code const&)
|
||||
{
|
||||
pure_virtual ();
|
||||
}
|
||||
|
||||
void TestPeerLogic::finished ()
|
||||
{
|
||||
pure_virtual ();
|
||||
}
|
||||
|
||||
void TestPeerLogic::pure_virtual ()
|
||||
{
|
||||
fatal_error ("A TestPeerLogic function was called incorrectly");
|
||||
}
|
||||
57
modules/beast_asio/tests/TestPeerLogic.h
Normal file
57
modules/beast_asio/tests/TestPeerLogic.h
Normal file
@@ -0,0 +1,57 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_TESTS_TESTPEERLOGIC_H_INCLUDED
|
||||
#define BEAST_ASIO_TESTS_TESTPEERLOGIC_H_INCLUDED
|
||||
|
||||
/** Interface for implementing the logic part of a peer test.
|
||||
*/
|
||||
class TestPeerLogic : public TestPeerBasics
|
||||
{
|
||||
public:
|
||||
typedef boost::system::error_code error_code;
|
||||
|
||||
explicit TestPeerLogic (Socket& socket);
|
||||
|
||||
error_code& error () noexcept;
|
||||
error_code const& error () const noexcept;
|
||||
error_code const& error (error_code const& ec) noexcept; // assigns to m_ec
|
||||
|
||||
Socket& socket () noexcept;
|
||||
|
||||
virtual PeerRole get_role () const noexcept = 0;
|
||||
|
||||
virtual Model get_model () const noexcept = 0;
|
||||
|
||||
virtual void on_connect ();
|
||||
|
||||
virtual void on_connect_async (error_code const&);
|
||||
|
||||
// asynchronous logic classes
|
||||
// must call this when they are done
|
||||
virtual void finished ();
|
||||
|
||||
static void pure_virtual ();
|
||||
|
||||
private:
|
||||
error_code m_ec;
|
||||
Socket* m_socket;
|
||||
};
|
||||
|
||||
#endif
|
||||
155
modules/beast_asio/tests/TestPeerLogicAsyncClient.cpp
Normal file
155
modules/beast_asio/tests/TestPeerLogicAsyncClient.cpp
Normal file
@@ -0,0 +1,155 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
TestPeerLogicAsyncClient::TestPeerLogicAsyncClient (Socket& socket)
|
||||
: TestPeerLogic (socket)
|
||||
{
|
||||
}
|
||||
|
||||
PeerRole TestPeerLogicAsyncClient::get_role () const noexcept
|
||||
{
|
||||
return PeerRole::client;
|
||||
}
|
||||
|
||||
TestPeerBasics::Model TestPeerLogicAsyncClient::get_model () const noexcept
|
||||
{
|
||||
return Model::async;
|
||||
}
|
||||
|
||||
void TestPeerLogicAsyncClient::on_connect_async (error_code const& ec)
|
||||
{
|
||||
if (aborted (ec) || failure (error (ec)))
|
||||
return finished ();
|
||||
|
||||
if (socket ().needs_handshake ())
|
||||
{
|
||||
socket ().async_handshake (Socket::client,
|
||||
boost::bind (&TestPeerLogicAsyncClient::on_handshake, this,
|
||||
boost::asio::placeholders::error));
|
||||
}
|
||||
else
|
||||
{
|
||||
on_handshake (ec);
|
||||
}
|
||||
}
|
||||
|
||||
void TestPeerLogicAsyncClient::on_handshake (error_code const& ec)
|
||||
{
|
||||
if (aborted (ec) || failure (error (ec)))
|
||||
return finished ();
|
||||
|
||||
boost::asio::async_write (socket (), boost::asio::buffer ("hello", 5),
|
||||
boost::bind (&TestPeerLogicAsyncClient::on_write, this,
|
||||
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
|
||||
}
|
||||
|
||||
void TestPeerLogicAsyncClient::on_write (error_code const& ec, std::size_t bytes_transferred)
|
||||
{
|
||||
if (aborted (ec) || failure (error (ec)))
|
||||
return finished ();
|
||||
|
||||
if (unexpected (bytes_transferred == 5, error ()))
|
||||
return finished ();
|
||||
|
||||
boost::asio::async_read_until (socket (), m_buf, std::string ("goodbye"),
|
||||
boost::bind (&TestPeerLogicAsyncClient::on_read, this,
|
||||
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
|
||||
}
|
||||
|
||||
void TestPeerLogicAsyncClient::on_read (error_code const& ec, std::size_t bytes_transferred)
|
||||
{
|
||||
if (aborted (ec) || failure (error (ec)))
|
||||
return finished ();
|
||||
|
||||
if (unexpected (bytes_transferred == 7, error ()))
|
||||
return finished ();
|
||||
|
||||
// should check the data here?
|
||||
m_buf.consume (bytes_transferred);
|
||||
|
||||
// Fire up a 1 byte read, to wait for the server to
|
||||
// shut down its end of the connection.
|
||||
boost::asio::async_read (socket (), m_buf.prepare (1),
|
||||
boost::bind (&TestPeerLogicAsyncClient::on_read_final, this,
|
||||
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
|
||||
}
|
||||
|
||||
void TestPeerLogicAsyncClient::on_read_final (error_code const& ec, std::size_t)
|
||||
{
|
||||
if (aborted (ec))
|
||||
return finished ();
|
||||
|
||||
// An eof is the normal case. The server should have closed shop.
|
||||
//
|
||||
if (ec == boost::asio::error::eof)
|
||||
{
|
||||
if (socket ().needs_handshake ())
|
||||
{
|
||||
socket ().async_shutdown (boost::bind (&TestPeerLogicAsyncClient::on_shutdown, this,
|
||||
boost::asio::placeholders::error));
|
||||
}
|
||||
else
|
||||
{
|
||||
// on_shutdown will call finished ()
|
||||
error_code ec;
|
||||
on_shutdown (socket ().shutdown (Socket::shutdown_both, ec));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we don't get eof, then there should be some other
|
||||
// error in there. We don't expect the server to send more bytes!
|
||||
//
|
||||
// This statement will do the following:
|
||||
//
|
||||
// error (ec) save ec into our error state
|
||||
// success () return true if ec represents success
|
||||
// unexpected () changes error() to 'unexpected' result if
|
||||
// success() returned true
|
||||
//
|
||||
unexpected (success (error (ec)), error ());
|
||||
|
||||
return finished ();
|
||||
}
|
||||
}
|
||||
|
||||
void TestPeerLogicAsyncClient::on_shutdown (error_code const& ec)
|
||||
{
|
||||
if (! aborted (ec))
|
||||
{
|
||||
if (success (error (ec), true))
|
||||
{
|
||||
if (socket ().needs_handshake ())
|
||||
{
|
||||
socket ().shutdown (Socket::shutdown_both, error ());
|
||||
}
|
||||
|
||||
if (! error ())
|
||||
{
|
||||
if (success (socket ().close (error ())))
|
||||
{
|
||||
// doing nothing here is intended,
|
||||
// as the calls to success() may set error()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
finished ();
|
||||
}
|
||||
39
modules/beast_asio/tests/TestPeerLogicAsyncClient.h
Normal file
39
modules/beast_asio/tests/TestPeerLogicAsyncClient.h
Normal file
@@ -0,0 +1,39 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_TESTS_TESTPEERLOGICASYNCCLIENT_H_INCLUDED
|
||||
#define BEAST_ASIO_TESTS_TESTPEERLOGICASYNCCLIENT_H_INCLUDED
|
||||
|
||||
class TestPeerLogicAsyncClient : public TestPeerLogic
|
||||
{
|
||||
public:
|
||||
explicit TestPeerLogicAsyncClient (Socket& socket);
|
||||
PeerRole get_role () const noexcept;
|
||||
Model get_model () const noexcept;
|
||||
void on_connect_async (error_code const& ec);
|
||||
void on_handshake (error_code const& ec);
|
||||
void on_write (error_code const& ec, std::size_t bytes_transferred);
|
||||
void on_read (error_code const& ec, std::size_t bytes_transferred);
|
||||
void on_read_final (error_code const& ec, std::size_t);
|
||||
void on_shutdown (error_code const& ec);
|
||||
private:
|
||||
boost::asio::streambuf m_buf;
|
||||
};
|
||||
|
||||
#endif
|
||||
117
modules/beast_asio/tests/TestPeerLogicAsyncServer.cpp
Normal file
117
modules/beast_asio/tests/TestPeerLogicAsyncServer.cpp
Normal file
@@ -0,0 +1,117 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
TestPeerLogicAsyncServer::TestPeerLogicAsyncServer (Socket& socket)
|
||||
: TestPeerLogic (socket)
|
||||
{
|
||||
}
|
||||
|
||||
PeerRole TestPeerLogicAsyncServer::get_role () const noexcept
|
||||
{
|
||||
return PeerRole::server;
|
||||
}
|
||||
|
||||
TestPeerBasics::Model TestPeerLogicAsyncServer::get_model () const noexcept
|
||||
{
|
||||
return Model::async;
|
||||
}
|
||||
|
||||
void TestPeerLogicAsyncServer::on_connect_async (error_code const& ec)
|
||||
{
|
||||
if (aborted (ec) || failure (error (ec)))
|
||||
return finished ();
|
||||
|
||||
if (socket ().needs_handshake ())
|
||||
{
|
||||
socket ().async_handshake (Socket::server,
|
||||
boost::bind (&TestPeerLogicAsyncServer::on_handshake, this,
|
||||
boost::asio::placeholders::error));
|
||||
}
|
||||
else
|
||||
{
|
||||
on_handshake (ec);
|
||||
}
|
||||
}
|
||||
|
||||
void TestPeerLogicAsyncServer::on_handshake (error_code const& ec)
|
||||
{
|
||||
if (aborted (ec) || failure (error (ec)))
|
||||
return finished ();
|
||||
|
||||
boost::asio::async_read_until (socket (), m_buf, std::string ("hello"),
|
||||
boost::bind (&TestPeerLogicAsyncServer::on_read, this,
|
||||
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
|
||||
}
|
||||
|
||||
void TestPeerLogicAsyncServer::on_read (error_code const& ec, std::size_t bytes_transferred)
|
||||
{
|
||||
if (aborted (ec) || failure (error (ec)))
|
||||
return finished ();
|
||||
|
||||
if (unexpected (bytes_transferred == 5, error ()))
|
||||
return finished ();
|
||||
|
||||
boost::asio::async_write (socket (), boost::asio::buffer ("goodbye", 7),
|
||||
boost::bind (&TestPeerLogicAsyncServer::on_write, this,
|
||||
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
|
||||
}
|
||||
|
||||
void TestPeerLogicAsyncServer::on_write (error_code const& ec, std::size_t bytes_transferred)
|
||||
{
|
||||
if (aborted (ec) || failure (error (ec)))
|
||||
return finished ();
|
||||
|
||||
if (unexpected (bytes_transferred == 7, error ()))
|
||||
return finished ();
|
||||
|
||||
if (socket ().needs_handshake ())
|
||||
{
|
||||
socket ().async_shutdown (boost::bind (&TestPeerLogicAsyncServer::on_shutdown, this,
|
||||
boost::asio::placeholders::error));
|
||||
}
|
||||
else
|
||||
{
|
||||
// on_shutdown will call finished ()
|
||||
// we need another instance of ec so we can call on_shutdown()
|
||||
error_code ec;
|
||||
on_shutdown (socket ().shutdown (Socket::shutdown_both, ec));
|
||||
}
|
||||
}
|
||||
|
||||
void TestPeerLogicAsyncServer::on_shutdown (error_code const& ec)
|
||||
{
|
||||
if (! aborted (ec))
|
||||
{
|
||||
if (success (error (ec), true))
|
||||
{
|
||||
if (socket ().needs_handshake ())
|
||||
{
|
||||
socket ().shutdown (Socket::shutdown_both, error ());
|
||||
}
|
||||
|
||||
if (success (socket ().close (error ())))
|
||||
{
|
||||
// doing nothing here is intended,
|
||||
// as the calls to success() may set error()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
finished ();
|
||||
}
|
||||
38
modules/beast_asio/tests/TestPeerLogicAsyncServer.h
Normal file
38
modules/beast_asio/tests/TestPeerLogicAsyncServer.h
Normal file
@@ -0,0 +1,38 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_TESTS_TESTPEERLOGICASYNCSERVER_H_INCLUDED
|
||||
#define BEAST_ASIO_TESTS_TESTPEERLOGICASYNCSERVER_H_INCLUDED
|
||||
|
||||
class TestPeerLogicAsyncServer : public TestPeerLogic
|
||||
{
|
||||
public:
|
||||
explicit TestPeerLogicAsyncServer (Socket& socket);
|
||||
PeerRole get_role () const noexcept;
|
||||
Model get_model () const noexcept;
|
||||
void on_connect_async (error_code const& ec);
|
||||
void on_handshake (error_code const& ec);
|
||||
void on_read (error_code const& ec, std::size_t bytes_transferred);
|
||||
void on_write (error_code const& ec, std::size_t bytes_transferred);
|
||||
void on_shutdown (error_code const& ec);
|
||||
private:
|
||||
boost::asio::streambuf m_buf;
|
||||
};
|
||||
|
||||
#endif
|
||||
35
modules/beast_asio/tests/TestPeerLogicProxyClient.cpp
Normal file
35
modules/beast_asio/tests/TestPeerLogicProxyClient.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
TestPeerLogicProxyClient::TestPeerLogicProxyClient (Socket& socket)
|
||||
: TestPeerLogicSyncClient (socket)
|
||||
{
|
||||
}
|
||||
|
||||
void TestPeerLogicProxyClient::on_pre_handshake ()
|
||||
{
|
||||
//ProxyHandshakeParser h;
|
||||
|
||||
static std::string line (
|
||||
"PROXY TCP4 255.255.255.255 255.255.255.255 65535 65535\r\n"
|
||||
// 56 chars
|
||||
);
|
||||
|
||||
boost::asio::write (socket (), boost::asio::buffer (line), error ());
|
||||
}
|
||||
31
modules/beast_asio/tests/TestPeerLogicProxyClient.h
Normal file
31
modules/beast_asio/tests/TestPeerLogicProxyClient.h
Normal file
@@ -0,0 +1,31 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_TESTS_TESTPEERLOGICPROXYCLIENT_H_INCLUDED
|
||||
#define BEAST_ASIO_TESTS_TESTPEERLOGICPROXYCLIENT_H_INCLUDED
|
||||
|
||||
/** A synchronous client logic that sends a PROXY protocol pre-handshake. */
|
||||
class TestPeerLogicProxyClient : public TestPeerLogicSyncClient
|
||||
{
|
||||
public:
|
||||
explicit TestPeerLogicProxyClient (Socket& socket);
|
||||
void on_pre_handshake ();
|
||||
};
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user