Compare commits
1 Commits
winconsole
...
zmq
| Author | SHA1 | Date | |
|---|---|---|---|
| c1d20d2c41 |
224
.clang-format
224
.clang-format
@@ -1,224 +0,0 @@
|
||||
---
|
||||
Language: Cpp
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignArrayOfStructures: Left
|
||||
AlignConsecutiveAssignments:
|
||||
Enabled: true
|
||||
AcrossEmptyLines: true
|
||||
AcrossComments: true
|
||||
AlignCompound: false
|
||||
PadOperators: true
|
||||
AlignConsecutiveBitFields:
|
||||
Enabled: true
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: true
|
||||
AlignCompound: false
|
||||
PadOperators: true
|
||||
AlignConsecutiveDeclarations:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
PadOperators: false
|
||||
AlignConsecutiveMacros:
|
||||
Enabled: true
|
||||
AcrossEmptyLines: true
|
||||
AcrossComments: true
|
||||
AlignCompound: false
|
||||
PadOperators: true
|
||||
AlignEscapedNewlines: Left
|
||||
AlignOperands: Align
|
||||
AlignTrailingComments: true
|
||||
AllowAllArgumentsOnNextLine: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortEnumsOnASingleLine: false
|
||||
AllowShortBlocksOnASingleLine: Empty
|
||||
AllowShortCaseLabelsOnASingleLine: true
|
||||
AllowShortFunctionsOnASingleLine: Inline
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: WithoutElse
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
AttributeMacros:
|
||||
- __capability
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: false
|
||||
AfterControlStatement: Never
|
||||
AfterEnum: false
|
||||
AfterFunction: false
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
AfterExternBlock: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
BeforeLambdaBody: false
|
||||
BeforeWhile: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: false
|
||||
SplitEmptyRecord: false
|
||||
SplitEmptyNamespace: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeConceptDeclarations: Always
|
||||
BreakBeforeBraces: Attach
|
||||
BreakInheritanceList: BeforeComma
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializers: BeforeComma
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 140
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
QualifierAlignment: Leave
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DeriveLineEnding: false
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
EmptyLineAfterAccessModifier: Never
|
||||
EmptyLineBeforeAccessModifier: Always
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
PackConstructorInitializers: CurrentLine
|
||||
BasedOnStyle: ''
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
AllowAllConstructorInitializersOnNextLine: true
|
||||
FixNamespaceComments: true
|
||||
ForEachMacros:
|
||||
- foreach
|
||||
- Q_FOREACH
|
||||
- BOOST_FOREACH
|
||||
- piForeach
|
||||
- piForeachC
|
||||
- piForeachR
|
||||
- piForeachRC
|
||||
- piForeachCR
|
||||
IfMacros:
|
||||
- KJ_IF_MAYBE
|
||||
IncludeBlocks: Regroup
|
||||
IncludeCategories:
|
||||
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
|
||||
Priority: 2
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
|
||||
Priority: 3
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: '.*'
|
||||
Priority: 1
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
IncludeIsMainRegex: '(Test)?$'
|
||||
IncludeIsMainSourceRegex: ''
|
||||
IndentAccessModifiers: false
|
||||
IndentCaseLabels: false
|
||||
IndentCaseBlocks: false
|
||||
IndentGotoLabels: false
|
||||
IndentPPDirectives: AfterHash
|
||||
IndentExternBlock: NoIndent
|
||||
IndentRequiresClause: true
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: false
|
||||
InsertBraces: false
|
||||
InsertTrailingCommas: Wrapped
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
LambdaBodyIndentation: Signature
|
||||
MacroBlockBegin: "PRIVATE_DEFINITION_START|STATIC_INITIALIZER_BEGIN"
|
||||
MacroBlockEnd: "PRIVATE_DEFINITION_END|PRIVATE_DEFINITION_END_NO_INITIALIZE|STATIC_INITIALIZER_END"
|
||||
MaxEmptyLinesToKeep: 2
|
||||
NamespaceIndentation: None
|
||||
ObjCBinPackProtocolList: Auto
|
||||
ObjCBlockIndentWidth: 2
|
||||
ObjCBreakBeforeNestedBlockParam: true
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PenaltyBreakAssignment: 2
|
||||
PenaltyBreakBeforeFirstCallParameter: 19
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakOpenParenthesis: 0
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyBreakTemplateDeclaration: 10
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
PenaltyIndentedWhitespace: 0
|
||||
PointerAlignment: Middle
|
||||
PPIndentWidth: 2
|
||||
ReferenceAlignment: Middle
|
||||
ReflowComments: true
|
||||
RemoveBracesLLVM: false
|
||||
RequiresClausePosition: OwnLine
|
||||
SeparateDefinitionBlocks: Leave
|
||||
ShortNamespaceLines: 1
|
||||
SortIncludes: CaseSensitive
|
||||
SortJavaStaticImport: Before
|
||||
SortUsingDeclarations: true
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: false
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCaseColon: false
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceBeforeCtorInitializerColon: false
|
||||
SpaceBeforeInheritanceColon: false
|
||||
SpaceBeforeParens: ControlStatementsExceptControlMacros
|
||||
SpaceBeforeParensOptions:
|
||||
AfterControlStatements: true
|
||||
AfterForeachMacros: false
|
||||
AfterFunctionDefinitionName: false
|
||||
AfterFunctionDeclarationName: false
|
||||
AfterIfMacros: false
|
||||
AfterOverloadedOperator: false
|
||||
AfterRequiresInClause: false
|
||||
AfterRequiresInExpression: false
|
||||
BeforeNonEmptyParentheses: false
|
||||
SpaceAroundPointerQualifiers: Both
|
||||
SpaceBeforeRangeBasedForLoopColon: false
|
||||
SpaceInEmptyBlock: false
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: Never
|
||||
SpacesInConditionalStatement: false
|
||||
SpacesInContainerLiterals: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInLineCommentPrefix:
|
||||
Minimum: 1
|
||||
Maximum: -1
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
SpaceBeforeSquareBrackets: false
|
||||
BitFieldColonSpacing: After
|
||||
Standard: c++11
|
||||
StatementAttributeLikeMacros:
|
||||
- Q_EMIT
|
||||
- PIMETA
|
||||
StatementMacros:
|
||||
- Q_UNUSED
|
||||
- QT_REQUIRE_VERSION
|
||||
- PRIVATE_DECLARATION
|
||||
- NO_COPY_CLASS
|
||||
- FOREVER_WAIT
|
||||
- WAIT_FOREVER
|
||||
TabWidth: 4
|
||||
UseCRLF: false
|
||||
UseTab: AlignWithSpaces
|
||||
WhitespaceSensitiveMacros:
|
||||
- STRINGIZE
|
||||
- PP_STRINGIZE
|
||||
- BOOST_PP_STRINGIZE
|
||||
- NS_SWIFT_NAME
|
||||
- CF_SWIFT_NAME
|
||||
- PIMETA
|
||||
...
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
root = true
|
||||
|
||||
[*.{h,c,cpp}]
|
||||
charset = utf-8
|
||||
indent_style = tab
|
||||
tab_width = 4
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -3,6 +3,3 @@
|
||||
/doc/rtf
|
||||
_unsused
|
||||
CMakeLists.txt.user*
|
||||
/include
|
||||
/release
|
||||
/build*
|
||||
|
||||
@@ -1,160 +0,0 @@
|
||||
/*
|
||||
BLAKE2 reference source code package - reference C implementations
|
||||
|
||||
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
|
||||
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
|
||||
your option. The terms of these licenses can be found at:
|
||||
|
||||
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
|
||||
- OpenSSL license : https://www.openssl.org/source/license.html
|
||||
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
More information about the BLAKE2 hash function can be found at
|
||||
https://blake2.net.
|
||||
*/
|
||||
#ifndef BLAKE2_IMPL_H
|
||||
#define BLAKE2_IMPL_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#if !defined(__cplusplus) && (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L)
|
||||
#if defined(_MSC_VER)
|
||||
#define BLAKE2_INLINE __inline
|
||||
#elif defined(__GNUC__)
|
||||
#define BLAKE2_INLINE __inline__
|
||||
#else
|
||||
#define BLAKE2_INLINE
|
||||
#endif
|
||||
#else
|
||||
#define BLAKE2_INLINE inline
|
||||
#endif
|
||||
|
||||
static BLAKE2_INLINE uint32_t load32( const void *src )
|
||||
{
|
||||
#if defined(NATIVE_LITTLE_ENDIAN)
|
||||
uint32_t w;
|
||||
memcpy(&w, src, sizeof w);
|
||||
return w;
|
||||
#else
|
||||
const uint8_t *p = ( const uint8_t * )src;
|
||||
return (( uint32_t )( p[0] ) << 0) |
|
||||
(( uint32_t )( p[1] ) << 8) |
|
||||
(( uint32_t )( p[2] ) << 16) |
|
||||
(( uint32_t )( p[3] ) << 24) ;
|
||||
#endif
|
||||
}
|
||||
|
||||
static BLAKE2_INLINE uint64_t load64( const void *src )
|
||||
{
|
||||
#if defined(NATIVE_LITTLE_ENDIAN)
|
||||
uint64_t w;
|
||||
memcpy(&w, src, sizeof w);
|
||||
return w;
|
||||
#else
|
||||
const uint8_t *p = ( const uint8_t * )src;
|
||||
return (( uint64_t )( p[0] ) << 0) |
|
||||
(( uint64_t )( p[1] ) << 8) |
|
||||
(( uint64_t )( p[2] ) << 16) |
|
||||
(( uint64_t )( p[3] ) << 24) |
|
||||
(( uint64_t )( p[4] ) << 32) |
|
||||
(( uint64_t )( p[5] ) << 40) |
|
||||
(( uint64_t )( p[6] ) << 48) |
|
||||
(( uint64_t )( p[7] ) << 56) ;
|
||||
#endif
|
||||
}
|
||||
|
||||
static BLAKE2_INLINE uint16_t load16( const void *src )
|
||||
{
|
||||
#if defined(NATIVE_LITTLE_ENDIAN)
|
||||
uint16_t w;
|
||||
memcpy(&w, src, sizeof w);
|
||||
return w;
|
||||
#else
|
||||
const uint8_t *p = ( const uint8_t * )src;
|
||||
return ( uint16_t )((( uint32_t )( p[0] ) << 0) |
|
||||
(( uint32_t )( p[1] ) << 8));
|
||||
#endif
|
||||
}
|
||||
|
||||
static BLAKE2_INLINE void store16( void *dst, uint16_t w )
|
||||
{
|
||||
#if defined(NATIVE_LITTLE_ENDIAN)
|
||||
memcpy(dst, &w, sizeof w);
|
||||
#else
|
||||
uint8_t *p = ( uint8_t * )dst;
|
||||
*p++ = ( uint8_t )w; w >>= 8;
|
||||
*p++ = ( uint8_t )w;
|
||||
#endif
|
||||
}
|
||||
|
||||
static BLAKE2_INLINE void store32( void *dst, uint32_t w )
|
||||
{
|
||||
#if defined(NATIVE_LITTLE_ENDIAN)
|
||||
memcpy(dst, &w, sizeof w);
|
||||
#else
|
||||
uint8_t *p = ( uint8_t * )dst;
|
||||
p[0] = (uint8_t)(w >> 0);
|
||||
p[1] = (uint8_t)(w >> 8);
|
||||
p[2] = (uint8_t)(w >> 16);
|
||||
p[3] = (uint8_t)(w >> 24);
|
||||
#endif
|
||||
}
|
||||
|
||||
static BLAKE2_INLINE void store64( void *dst, uint64_t w )
|
||||
{
|
||||
#if defined(NATIVE_LITTLE_ENDIAN)
|
||||
memcpy(dst, &w, sizeof w);
|
||||
#else
|
||||
uint8_t *p = ( uint8_t * )dst;
|
||||
p[0] = (uint8_t)(w >> 0);
|
||||
p[1] = (uint8_t)(w >> 8);
|
||||
p[2] = (uint8_t)(w >> 16);
|
||||
p[3] = (uint8_t)(w >> 24);
|
||||
p[4] = (uint8_t)(w >> 32);
|
||||
p[5] = (uint8_t)(w >> 40);
|
||||
p[6] = (uint8_t)(w >> 48);
|
||||
p[7] = (uint8_t)(w >> 56);
|
||||
#endif
|
||||
}
|
||||
|
||||
static BLAKE2_INLINE uint64_t load48( const void *src )
|
||||
{
|
||||
const uint8_t *p = ( const uint8_t * )src;
|
||||
return (( uint64_t )( p[0] ) << 0) |
|
||||
(( uint64_t )( p[1] ) << 8) |
|
||||
(( uint64_t )( p[2] ) << 16) |
|
||||
(( uint64_t )( p[3] ) << 24) |
|
||||
(( uint64_t )( p[4] ) << 32) |
|
||||
(( uint64_t )( p[5] ) << 40) ;
|
||||
}
|
||||
|
||||
static BLAKE2_INLINE void store48( void *dst, uint64_t w )
|
||||
{
|
||||
uint8_t *p = ( uint8_t * )dst;
|
||||
p[0] = (uint8_t)(w >> 0);
|
||||
p[1] = (uint8_t)(w >> 8);
|
||||
p[2] = (uint8_t)(w >> 16);
|
||||
p[3] = (uint8_t)(w >> 24);
|
||||
p[4] = (uint8_t)(w >> 32);
|
||||
p[5] = (uint8_t)(w >> 40);
|
||||
}
|
||||
|
||||
static BLAKE2_INLINE uint32_t rotr32( const uint32_t w, const unsigned c )
|
||||
{
|
||||
return ( w >> c ) | ( w << ( 32 - c ) );
|
||||
}
|
||||
|
||||
static BLAKE2_INLINE uint64_t rotr64( const uint64_t w, const unsigned c )
|
||||
{
|
||||
return ( w >> c ) | ( w << ( 64 - c ) );
|
||||
}
|
||||
|
||||
/* prevents compiler optimizing out memset() */
|
||||
static BLAKE2_INLINE void secure_zero_memory(void *v, size_t n)
|
||||
{
|
||||
static void *(*const volatile memset_v)(void *, int, size_t) = &memset;
|
||||
memset_v(v, 0, n);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,195 +0,0 @@
|
||||
/*
|
||||
BLAKE2 reference source code package - reference C implementations
|
||||
|
||||
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
|
||||
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
|
||||
your option. The terms of these licenses can be found at:
|
||||
|
||||
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
|
||||
- OpenSSL license : https://www.openssl.org/source/license.html
|
||||
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
More information about the BLAKE2 hash function can be found at
|
||||
https://blake2.net.
|
||||
*/
|
||||
#ifndef BLAKE2_H
|
||||
#define BLAKE2_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define BLAKE2_PACKED(x) __pragma(pack(push, 1)) x __pragma(pack(pop))
|
||||
#else
|
||||
#define BLAKE2_PACKED(x) x __attribute__((packed))
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum blake2s_constant
|
||||
{
|
||||
BLAKE2S_BLOCKBYTES = 64,
|
||||
BLAKE2S_OUTBYTES = 32,
|
||||
BLAKE2S_KEYBYTES = 32,
|
||||
BLAKE2S_SALTBYTES = 8,
|
||||
BLAKE2S_PERSONALBYTES = 8
|
||||
};
|
||||
|
||||
enum blake2b_constant
|
||||
{
|
||||
BLAKE2B_BLOCKBYTES = 128,
|
||||
BLAKE2B_OUTBYTES = 64,
|
||||
BLAKE2B_KEYBYTES = 64,
|
||||
BLAKE2B_SALTBYTES = 16,
|
||||
BLAKE2B_PERSONALBYTES = 16
|
||||
};
|
||||
|
||||
typedef struct blake2s_state__
|
||||
{
|
||||
uint32_t h[8];
|
||||
uint32_t t[2];
|
||||
uint32_t f[2];
|
||||
uint8_t buf[BLAKE2S_BLOCKBYTES];
|
||||
size_t buflen;
|
||||
size_t outlen;
|
||||
uint8_t last_node;
|
||||
} blake2s_state;
|
||||
|
||||
typedef struct blake2b_state__
|
||||
{
|
||||
uint64_t h[8];
|
||||
uint64_t t[2];
|
||||
uint64_t f[2];
|
||||
uint8_t buf[BLAKE2B_BLOCKBYTES];
|
||||
size_t buflen;
|
||||
size_t outlen;
|
||||
uint8_t last_node;
|
||||
} blake2b_state;
|
||||
|
||||
typedef struct blake2sp_state__
|
||||
{
|
||||
blake2s_state S[8][1];
|
||||
blake2s_state R[1];
|
||||
uint8_t buf[8 * BLAKE2S_BLOCKBYTES];
|
||||
size_t buflen;
|
||||
size_t outlen;
|
||||
} blake2sp_state;
|
||||
|
||||
typedef struct blake2bp_state__
|
||||
{
|
||||
blake2b_state S[4][1];
|
||||
blake2b_state R[1];
|
||||
uint8_t buf[4 * BLAKE2B_BLOCKBYTES];
|
||||
size_t buflen;
|
||||
size_t outlen;
|
||||
} blake2bp_state;
|
||||
|
||||
|
||||
BLAKE2_PACKED(struct blake2s_param__
|
||||
{
|
||||
uint8_t digest_length; /* 1 */
|
||||
uint8_t key_length; /* 2 */
|
||||
uint8_t fanout; /* 3 */
|
||||
uint8_t depth; /* 4 */
|
||||
uint32_t leaf_length; /* 8 */
|
||||
uint32_t node_offset; /* 12 */
|
||||
uint16_t xof_length; /* 14 */
|
||||
uint8_t node_depth; /* 15 */
|
||||
uint8_t inner_length; /* 16 */
|
||||
/* uint8_t reserved[0]; */
|
||||
uint8_t salt[BLAKE2S_SALTBYTES]; /* 24 */
|
||||
uint8_t personal[BLAKE2S_PERSONALBYTES]; /* 32 */
|
||||
});
|
||||
|
||||
typedef struct blake2s_param__ blake2s_param;
|
||||
|
||||
BLAKE2_PACKED(struct blake2b_param__
|
||||
{
|
||||
uint8_t digest_length; /* 1 */
|
||||
uint8_t key_length; /* 2 */
|
||||
uint8_t fanout; /* 3 */
|
||||
uint8_t depth; /* 4 */
|
||||
uint32_t leaf_length; /* 8 */
|
||||
uint32_t node_offset; /* 12 */
|
||||
uint32_t xof_length; /* 16 */
|
||||
uint8_t node_depth; /* 17 */
|
||||
uint8_t inner_length; /* 18 */
|
||||
uint8_t reserved[14]; /* 32 */
|
||||
uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */
|
||||
uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */
|
||||
});
|
||||
|
||||
typedef struct blake2b_param__ blake2b_param;
|
||||
|
||||
typedef struct blake2xs_state__
|
||||
{
|
||||
blake2s_state S[1];
|
||||
blake2s_param P[1];
|
||||
} blake2xs_state;
|
||||
|
||||
typedef struct blake2xb_state__
|
||||
{
|
||||
blake2b_state S[1];
|
||||
blake2b_param P[1];
|
||||
} blake2xb_state;
|
||||
|
||||
/* Padded structs result in a compile-time error */
|
||||
enum {
|
||||
BLAKE2_DUMMY_1 = 1/(int)(sizeof(blake2s_param) == BLAKE2S_OUTBYTES),
|
||||
BLAKE2_DUMMY_2 = 1/(int)(sizeof(blake2b_param) == BLAKE2B_OUTBYTES)
|
||||
};
|
||||
|
||||
/* Streaming API */
|
||||
int blake2s_init( blake2s_state *S, size_t outlen );
|
||||
int blake2s_init_key( blake2s_state *S, size_t outlen, const void *key, size_t keylen );
|
||||
int blake2s_init_param( blake2s_state *S, const blake2s_param *P );
|
||||
int blake2s_update( blake2s_state *S, const void *in, size_t inlen );
|
||||
int blake2s_final( blake2s_state *S, void *out, size_t outlen );
|
||||
|
||||
int blake2b_init( blake2b_state *S, size_t outlen );
|
||||
int blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen );
|
||||
int blake2b_init_param( blake2b_state *S, const blake2b_param *P );
|
||||
int blake2b_update( blake2b_state *S, const void *in, size_t inlen );
|
||||
int blake2b_final( blake2b_state *S, void *out, size_t outlen );
|
||||
|
||||
int blake2sp_init( blake2sp_state *S, size_t outlen );
|
||||
int blake2sp_init_key( blake2sp_state *S, size_t outlen, const void *key, size_t keylen );
|
||||
int blake2sp_update( blake2sp_state *S, const void *in, size_t inlen );
|
||||
int blake2sp_final( blake2sp_state *S, void *out, size_t outlen );
|
||||
|
||||
int blake2bp_init( blake2bp_state *S, size_t outlen );
|
||||
int blake2bp_init_key( blake2bp_state *S, size_t outlen, const void *key, size_t keylen );
|
||||
int blake2bp_update( blake2bp_state *S, const void *in, size_t inlen );
|
||||
int blake2bp_final( blake2bp_state *S, void *out, size_t outlen );
|
||||
|
||||
/* Variable output length API */
|
||||
int blake2xs_init( blake2xs_state *S, const size_t outlen );
|
||||
int blake2xs_init_key( blake2xs_state *S, const size_t outlen, const void *key, size_t keylen );
|
||||
int blake2xs_update( blake2xs_state *S, const void *in, size_t inlen );
|
||||
int blake2xs_final(blake2xs_state *S, void *out, size_t outlen);
|
||||
|
||||
int blake2xb_init( blake2xb_state *S, const size_t outlen );
|
||||
int blake2xb_init_key( blake2xb_state *S, const size_t outlen, const void *key, size_t keylen );
|
||||
int blake2xb_update( blake2xb_state *S, const void *in, size_t inlen );
|
||||
int blake2xb_final(blake2xb_state *S, void *out, size_t outlen);
|
||||
|
||||
/* Simple API */
|
||||
int blake2s( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
||||
int blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
||||
|
||||
int blake2sp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
||||
int blake2bp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
||||
|
||||
int blake2xs( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
||||
int blake2xb( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
||||
|
||||
/* This is simply an alias for blake2b */
|
||||
int blake2( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,379 +0,0 @@
|
||||
/*
|
||||
BLAKE2 reference source code package - reference C implementations
|
||||
|
||||
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
|
||||
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
|
||||
your option. The terms of these licenses can be found at:
|
||||
|
||||
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
|
||||
- OpenSSL license : https://www.openssl.org/source/license.html
|
||||
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
More information about the BLAKE2 hash function can be found at
|
||||
https://blake2.net.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "blake2.h"
|
||||
#include "blake2-impl.h"
|
||||
|
||||
static const uint64_t blake2b_IV[8] =
|
||||
{
|
||||
0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
|
||||
0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
|
||||
0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
|
||||
0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
|
||||
};
|
||||
|
||||
static const uint8_t blake2b_sigma[12][16] =
|
||||
{
|
||||
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
|
||||
{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } ,
|
||||
{ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } ,
|
||||
{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } ,
|
||||
{ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } ,
|
||||
{ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } ,
|
||||
{ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } ,
|
||||
{ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } ,
|
||||
{ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } ,
|
||||
{ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } ,
|
||||
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
|
||||
{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }
|
||||
};
|
||||
|
||||
|
||||
static void blake2b_set_lastnode( blake2b_state *S )
|
||||
{
|
||||
S->f[1] = (uint64_t)-1;
|
||||
}
|
||||
|
||||
/* Some helper functions, not necessarily useful */
|
||||
static int blake2b_is_lastblock( const blake2b_state *S )
|
||||
{
|
||||
return S->f[0] != 0;
|
||||
}
|
||||
|
||||
static void blake2b_set_lastblock( blake2b_state *S )
|
||||
{
|
||||
if( S->last_node ) blake2b_set_lastnode( S );
|
||||
|
||||
S->f[0] = (uint64_t)-1;
|
||||
}
|
||||
|
||||
static void blake2b_increment_counter( blake2b_state *S, const uint64_t inc )
|
||||
{
|
||||
S->t[0] += inc;
|
||||
S->t[1] += ( S->t[0] < inc );
|
||||
}
|
||||
|
||||
static void blake2b_init0( blake2b_state *S )
|
||||
{
|
||||
size_t i;
|
||||
memset( S, 0, sizeof( blake2b_state ) );
|
||||
|
||||
for( i = 0; i < 8; ++i ) S->h[i] = blake2b_IV[i];
|
||||
}
|
||||
|
||||
/* init xors IV with input parameter block */
|
||||
int blake2b_init_param( blake2b_state *S, const blake2b_param *P )
|
||||
{
|
||||
const uint8_t *p = ( const uint8_t * )( P );
|
||||
size_t i;
|
||||
|
||||
blake2b_init0( S );
|
||||
|
||||
/* IV XOR ParamBlock */
|
||||
for( i = 0; i < 8; ++i )
|
||||
S->h[i] ^= load64( p + sizeof( S->h[i] ) * i );
|
||||
|
||||
S->outlen = P->digest_length;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int blake2b_init( blake2b_state *S, size_t outlen )
|
||||
{
|
||||
blake2b_param P[1];
|
||||
|
||||
if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1;
|
||||
|
||||
P->digest_length = (uint8_t)outlen;
|
||||
P->key_length = 0;
|
||||
P->fanout = 1;
|
||||
P->depth = 1;
|
||||
store32( &P->leaf_length, 0 );
|
||||
store32( &P->node_offset, 0 );
|
||||
store32( &P->xof_length, 0 );
|
||||
P->node_depth = 0;
|
||||
P->inner_length = 0;
|
||||
memset( P->reserved, 0, sizeof( P->reserved ) );
|
||||
memset( P->salt, 0, sizeof( P->salt ) );
|
||||
memset( P->personal, 0, sizeof( P->personal ) );
|
||||
return blake2b_init_param( S, P );
|
||||
}
|
||||
|
||||
|
||||
int blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen )
|
||||
{
|
||||
blake2b_param P[1];
|
||||
|
||||
if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1;
|
||||
|
||||
if ( !key || !keylen || keylen > BLAKE2B_KEYBYTES ) return -1;
|
||||
|
||||
P->digest_length = (uint8_t)outlen;
|
||||
P->key_length = (uint8_t)keylen;
|
||||
P->fanout = 1;
|
||||
P->depth = 1;
|
||||
store32( &P->leaf_length, 0 );
|
||||
store32( &P->node_offset, 0 );
|
||||
store32( &P->xof_length, 0 );
|
||||
P->node_depth = 0;
|
||||
P->inner_length = 0;
|
||||
memset( P->reserved, 0, sizeof( P->reserved ) );
|
||||
memset( P->salt, 0, sizeof( P->salt ) );
|
||||
memset( P->personal, 0, sizeof( P->personal ) );
|
||||
|
||||
if( blake2b_init_param( S, P ) < 0 ) return -1;
|
||||
|
||||
{
|
||||
uint8_t block[BLAKE2B_BLOCKBYTES];
|
||||
memset( block, 0, BLAKE2B_BLOCKBYTES );
|
||||
memcpy( block, key, keylen );
|
||||
blake2b_update( S, block, BLAKE2B_BLOCKBYTES );
|
||||
secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define G(r,i,a,b,c,d) \
|
||||
do { \
|
||||
a = a + b + m[blake2b_sigma[r][2*i+0]]; \
|
||||
d = rotr64(d ^ a, 32); \
|
||||
c = c + d; \
|
||||
b = rotr64(b ^ c, 24); \
|
||||
a = a + b + m[blake2b_sigma[r][2*i+1]]; \
|
||||
d = rotr64(d ^ a, 16); \
|
||||
c = c + d; \
|
||||
b = rotr64(b ^ c, 63); \
|
||||
} while(0)
|
||||
|
||||
#define ROUND(r) \
|
||||
do { \
|
||||
G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \
|
||||
G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \
|
||||
G(r,2,v[ 2],v[ 6],v[10],v[14]); \
|
||||
G(r,3,v[ 3],v[ 7],v[11],v[15]); \
|
||||
G(r,4,v[ 0],v[ 5],v[10],v[15]); \
|
||||
G(r,5,v[ 1],v[ 6],v[11],v[12]); \
|
||||
G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \
|
||||
G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \
|
||||
} while(0)
|
||||
|
||||
static void blake2b_compress( blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES] )
|
||||
{
|
||||
uint64_t m[16];
|
||||
uint64_t v[16];
|
||||
size_t i;
|
||||
|
||||
for( i = 0; i < 16; ++i ) {
|
||||
m[i] = load64( block + i * sizeof( m[i] ) );
|
||||
}
|
||||
|
||||
for( i = 0; i < 8; ++i ) {
|
||||
v[i] = S->h[i];
|
||||
}
|
||||
|
||||
v[ 8] = blake2b_IV[0];
|
||||
v[ 9] = blake2b_IV[1];
|
||||
v[10] = blake2b_IV[2];
|
||||
v[11] = blake2b_IV[3];
|
||||
v[12] = blake2b_IV[4] ^ S->t[0];
|
||||
v[13] = blake2b_IV[5] ^ S->t[1];
|
||||
v[14] = blake2b_IV[6] ^ S->f[0];
|
||||
v[15] = blake2b_IV[7] ^ S->f[1];
|
||||
|
||||
ROUND( 0 );
|
||||
ROUND( 1 );
|
||||
ROUND( 2 );
|
||||
ROUND( 3 );
|
||||
ROUND( 4 );
|
||||
ROUND( 5 );
|
||||
ROUND( 6 );
|
||||
ROUND( 7 );
|
||||
ROUND( 8 );
|
||||
ROUND( 9 );
|
||||
ROUND( 10 );
|
||||
ROUND( 11 );
|
||||
|
||||
for( i = 0; i < 8; ++i ) {
|
||||
S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
|
||||
}
|
||||
}
|
||||
|
||||
#undef G
|
||||
#undef ROUND
|
||||
|
||||
int blake2b_update( blake2b_state *S, const void *pin, size_t inlen )
|
||||
{
|
||||
const unsigned char * in = (const unsigned char *)pin;
|
||||
if( inlen > 0 )
|
||||
{
|
||||
size_t left = S->buflen;
|
||||
size_t fill = BLAKE2B_BLOCKBYTES - left;
|
||||
if( inlen > fill )
|
||||
{
|
||||
S->buflen = 0;
|
||||
memcpy( S->buf + left, in, fill ); /* Fill buffer */
|
||||
blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES );
|
||||
blake2b_compress( S, S->buf ); /* Compress */
|
||||
in += fill; inlen -= fill;
|
||||
while(inlen > BLAKE2B_BLOCKBYTES) {
|
||||
blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);
|
||||
blake2b_compress( S, in );
|
||||
in += BLAKE2B_BLOCKBYTES;
|
||||
inlen -= BLAKE2B_BLOCKBYTES;
|
||||
}
|
||||
}
|
||||
memcpy( S->buf + S->buflen, in, inlen );
|
||||
S->buflen += inlen;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blake2b_final( blake2b_state *S, void *out, size_t outlen )
|
||||
{
|
||||
uint8_t buffer[BLAKE2B_OUTBYTES] = {0};
|
||||
size_t i;
|
||||
|
||||
if( out == NULL || outlen < S->outlen )
|
||||
return -1;
|
||||
|
||||
if( blake2b_is_lastblock( S ) )
|
||||
return -1;
|
||||
|
||||
blake2b_increment_counter( S, S->buflen );
|
||||
blake2b_set_lastblock( S );
|
||||
memset( S->buf + S->buflen, 0, BLAKE2B_BLOCKBYTES - S->buflen ); /* Padding */
|
||||
blake2b_compress( S, S->buf );
|
||||
|
||||
for( i = 0; i < 8; ++i ) /* Output full hash to temp buffer */
|
||||
store64( buffer + sizeof( S->h[i] ) * i, S->h[i] );
|
||||
|
||||
memcpy( out, buffer, S->outlen );
|
||||
secure_zero_memory(buffer, sizeof(buffer));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* inlen, at least, should be uint64_t. Others can be size_t. */
|
||||
int blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )
|
||||
{
|
||||
blake2b_state S[1];
|
||||
|
||||
/* Verify parameters */
|
||||
if ( NULL == in && inlen > 0 ) return -1;
|
||||
|
||||
if ( NULL == out ) return -1;
|
||||
|
||||
if( NULL == key && keylen > 0 ) return -1;
|
||||
|
||||
if( !outlen || outlen > BLAKE2B_OUTBYTES ) return -1;
|
||||
|
||||
if( keylen > BLAKE2B_KEYBYTES ) return -1;
|
||||
|
||||
if( keylen > 0 )
|
||||
{
|
||||
if( blake2b_init_key( S, outlen, key, keylen ) < 0 ) return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( blake2b_init( S, outlen ) < 0 ) return -1;
|
||||
}
|
||||
|
||||
blake2b_update( S, ( const uint8_t * )in, inlen );
|
||||
blake2b_final( S, out, outlen );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blake2( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ) {
|
||||
return blake2b(out, outlen, in, inlen, key, keylen);
|
||||
}
|
||||
|
||||
#if defined(SUPERCOP)
|
||||
int crypto_hash( unsigned char *out, unsigned char *in, unsigned long long inlen )
|
||||
{
|
||||
return blake2b( out, BLAKE2B_OUTBYTES, in, inlen, NULL, 0 );
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(BLAKE2B_SELFTEST)
|
||||
#include <string.h>
|
||||
#include "blake2-kat.h"
|
||||
int main( void )
|
||||
{
|
||||
uint8_t key[BLAKE2B_KEYBYTES];
|
||||
uint8_t buf[BLAKE2_KAT_LENGTH];
|
||||
size_t i, step;
|
||||
|
||||
for( i = 0; i < BLAKE2B_KEYBYTES; ++i )
|
||||
key[i] = ( uint8_t )i;
|
||||
|
||||
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
|
||||
buf[i] = ( uint8_t )i;
|
||||
|
||||
/* Test simple API */
|
||||
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
|
||||
{
|
||||
uint8_t hash[BLAKE2B_OUTBYTES];
|
||||
blake2b( hash, BLAKE2B_OUTBYTES, buf, i, key, BLAKE2B_KEYBYTES );
|
||||
|
||||
if( 0 != memcmp( hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES ) )
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* Test streaming API */
|
||||
for(step = 1; step < BLAKE2B_BLOCKBYTES; ++step) {
|
||||
for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) {
|
||||
uint8_t hash[BLAKE2B_OUTBYTES];
|
||||
blake2b_state S;
|
||||
uint8_t * p = buf;
|
||||
size_t mlen = i;
|
||||
int err = 0;
|
||||
|
||||
if( (err = blake2b_init_key(&S, BLAKE2B_OUTBYTES, key, BLAKE2B_KEYBYTES)) < 0 ) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
while (mlen >= step) {
|
||||
if ( (err = blake2b_update(&S, p, step)) < 0 ) {
|
||||
goto fail;
|
||||
}
|
||||
mlen -= step;
|
||||
p += step;
|
||||
}
|
||||
if ( (err = blake2b_update(&S, p, mlen)) < 0) {
|
||||
goto fail;
|
||||
}
|
||||
if ( (err = blake2b_final(&S, hash, BLAKE2B_OUTBYTES)) < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (0 != memcmp(hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES)) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
puts( "ok" );
|
||||
return 0;
|
||||
fail:
|
||||
puts("error");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
@@ -1,359 +0,0 @@
|
||||
/*
|
||||
BLAKE2 reference source code package - reference C implementations
|
||||
|
||||
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
|
||||
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
|
||||
your option. The terms of these licenses can be found at:
|
||||
|
||||
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
|
||||
- OpenSSL license : https://www.openssl.org/source/license.html
|
||||
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
More information about the BLAKE2 hash function can be found at
|
||||
https://blake2.net.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#include <omp.h>
|
||||
#endif
|
||||
|
||||
#include "blake2.h"
|
||||
#include "blake2-impl.h"
|
||||
|
||||
#define PARALLELISM_DEGREE 4
|
||||
|
||||
/*
|
||||
blake2b_init_param defaults to setting the expecting output length
|
||||
from the digest_length parameter block field.
|
||||
|
||||
In some cases, however, we do not want this, as the output length
|
||||
of these instances is given by inner_length instead.
|
||||
*/
|
||||
static int blake2bp_init_leaf_param( blake2b_state *S, const blake2b_param *P )
|
||||
{
|
||||
int err = blake2b_init_param(S, P);
|
||||
S->outlen = P->inner_length;
|
||||
return err;
|
||||
}
|
||||
|
||||
static int blake2bp_init_leaf( blake2b_state *S, size_t outlen, size_t keylen, uint64_t offset )
|
||||
{
|
||||
blake2b_param P[1];
|
||||
P->digest_length = (uint8_t)outlen;
|
||||
P->key_length = (uint8_t)keylen;
|
||||
P->fanout = PARALLELISM_DEGREE;
|
||||
P->depth = 2;
|
||||
store32( &P->leaf_length, 0 );
|
||||
store32( &P->node_offset, offset );
|
||||
store32( &P->xof_length, 0 );
|
||||
P->node_depth = 0;
|
||||
P->inner_length = BLAKE2B_OUTBYTES;
|
||||
memset( P->reserved, 0, sizeof( P->reserved ) );
|
||||
memset( P->salt, 0, sizeof( P->salt ) );
|
||||
memset( P->personal, 0, sizeof( P->personal ) );
|
||||
return blake2bp_init_leaf_param( S, P );
|
||||
}
|
||||
|
||||
static int blake2bp_init_root( blake2b_state *S, size_t outlen, size_t keylen )
|
||||
{
|
||||
blake2b_param P[1];
|
||||
P->digest_length = (uint8_t)outlen;
|
||||
P->key_length = (uint8_t)keylen;
|
||||
P->fanout = PARALLELISM_DEGREE;
|
||||
P->depth = 2;
|
||||
store32( &P->leaf_length, 0 );
|
||||
store32( &P->node_offset, 0 );
|
||||
store32( &P->xof_length, 0 );
|
||||
P->node_depth = 1;
|
||||
P->inner_length = BLAKE2B_OUTBYTES;
|
||||
memset( P->reserved, 0, sizeof( P->reserved ) );
|
||||
memset( P->salt, 0, sizeof( P->salt ) );
|
||||
memset( P->personal, 0, sizeof( P->personal ) );
|
||||
return blake2b_init_param( S, P );
|
||||
}
|
||||
|
||||
|
||||
int blake2bp_init( blake2bp_state *S, size_t outlen )
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if( !outlen || outlen > BLAKE2B_OUTBYTES ) return -1;
|
||||
|
||||
memset( S->buf, 0, sizeof( S->buf ) );
|
||||
S->buflen = 0;
|
||||
S->outlen = outlen;
|
||||
|
||||
if( blake2bp_init_root( S->R, outlen, 0 ) < 0 )
|
||||
return -1;
|
||||
|
||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||
if( blake2bp_init_leaf( S->S[i], outlen, 0, i ) < 0 ) return -1;
|
||||
|
||||
S->R->last_node = 1;
|
||||
S->S[PARALLELISM_DEGREE - 1]->last_node = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blake2bp_init_key( blake2bp_state *S, size_t outlen, const void *key, size_t keylen )
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if( !outlen || outlen > BLAKE2B_OUTBYTES ) return -1;
|
||||
|
||||
if( !key || !keylen || keylen > BLAKE2B_KEYBYTES ) return -1;
|
||||
|
||||
memset( S->buf, 0, sizeof( S->buf ) );
|
||||
S->buflen = 0;
|
||||
S->outlen = outlen;
|
||||
|
||||
if( blake2bp_init_root( S->R, outlen, keylen ) < 0 )
|
||||
return -1;
|
||||
|
||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||
if( blake2bp_init_leaf( S->S[i], outlen, keylen, i ) < 0 ) return -1;
|
||||
|
||||
S->R->last_node = 1;
|
||||
S->S[PARALLELISM_DEGREE - 1]->last_node = 1;
|
||||
{
|
||||
uint8_t block[BLAKE2B_BLOCKBYTES];
|
||||
memset( block, 0, BLAKE2B_BLOCKBYTES );
|
||||
memcpy( block, key, keylen );
|
||||
|
||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||
blake2b_update( S->S[i], block, BLAKE2B_BLOCKBYTES );
|
||||
|
||||
secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int blake2bp_update( blake2bp_state *S, const void *pin, size_t inlen )
|
||||
{
|
||||
const unsigned char * in = (const unsigned char *)pin;
|
||||
size_t left = S->buflen;
|
||||
size_t fill = sizeof( S->buf ) - left;
|
||||
size_t i;
|
||||
|
||||
if( left && inlen >= fill )
|
||||
{
|
||||
memcpy( S->buf + left, in, fill );
|
||||
|
||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||
blake2b_update( S->S[i], S->buf + i * BLAKE2B_BLOCKBYTES, BLAKE2B_BLOCKBYTES );
|
||||
|
||||
in += fill;
|
||||
inlen -= fill;
|
||||
left = 0;
|
||||
}
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel shared(S), num_threads(PARALLELISM_DEGREE)
|
||||
#else
|
||||
|
||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||
#endif
|
||||
{
|
||||
#if defined(_OPENMP)
|
||||
size_t i = omp_get_thread_num();
|
||||
#endif
|
||||
size_t inlen__ = inlen;
|
||||
const unsigned char *in__ = ( const unsigned char * )in;
|
||||
in__ += i * BLAKE2B_BLOCKBYTES;
|
||||
|
||||
while( inlen__ >= PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES )
|
||||
{
|
||||
blake2b_update( S->S[i], in__, BLAKE2B_BLOCKBYTES );
|
||||
in__ += PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES;
|
||||
inlen__ -= PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES;
|
||||
}
|
||||
}
|
||||
|
||||
in += inlen - inlen % ( PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES );
|
||||
inlen %= PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES;
|
||||
|
||||
if( inlen > 0 )
|
||||
memcpy( S->buf + left, in, inlen );
|
||||
|
||||
S->buflen = left + inlen;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blake2bp_final( blake2bp_state *S, void *out, size_t outlen )
|
||||
{
|
||||
uint8_t hash[PARALLELISM_DEGREE][BLAKE2B_OUTBYTES];
|
||||
size_t i;
|
||||
|
||||
if(out == NULL || outlen < S->outlen) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||
{
|
||||
if( S->buflen > i * BLAKE2B_BLOCKBYTES )
|
||||
{
|
||||
size_t left = S->buflen - i * BLAKE2B_BLOCKBYTES;
|
||||
|
||||
if( left > BLAKE2B_BLOCKBYTES ) left = BLAKE2B_BLOCKBYTES;
|
||||
|
||||
blake2b_update( S->S[i], S->buf + i * BLAKE2B_BLOCKBYTES, left );
|
||||
}
|
||||
|
||||
blake2b_final( S->S[i], hash[i], BLAKE2B_OUTBYTES );
|
||||
}
|
||||
|
||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||
blake2b_update( S->R, hash[i], BLAKE2B_OUTBYTES );
|
||||
|
||||
return blake2b_final( S->R, out, S->outlen );
|
||||
}
|
||||
|
||||
int blake2bp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )
|
||||
{
|
||||
uint8_t hash[PARALLELISM_DEGREE][BLAKE2B_OUTBYTES];
|
||||
blake2b_state S[PARALLELISM_DEGREE][1];
|
||||
blake2b_state FS[1];
|
||||
size_t i;
|
||||
|
||||
/* Verify parameters */
|
||||
if ( NULL == in && inlen > 0 ) return -1;
|
||||
|
||||
if ( NULL == out ) return -1;
|
||||
|
||||
if( NULL == key && keylen > 0 ) return -1;
|
||||
|
||||
if( !outlen || outlen > BLAKE2B_OUTBYTES ) return -1;
|
||||
|
||||
if( keylen > BLAKE2B_KEYBYTES ) return -1;
|
||||
|
||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||
if( blake2bp_init_leaf( S[i], outlen, keylen, i ) < 0 ) return -1;
|
||||
|
||||
S[PARALLELISM_DEGREE - 1]->last_node = 1; /* mark last node */
|
||||
|
||||
if( keylen > 0 )
|
||||
{
|
||||
uint8_t block[BLAKE2B_BLOCKBYTES];
|
||||
memset( block, 0, BLAKE2B_BLOCKBYTES );
|
||||
memcpy( block, key, keylen );
|
||||
|
||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||
blake2b_update( S[i], block, BLAKE2B_BLOCKBYTES );
|
||||
|
||||
secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */
|
||||
}
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel shared(S,hash), num_threads(PARALLELISM_DEGREE)
|
||||
#else
|
||||
|
||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||
#endif
|
||||
{
|
||||
#if defined(_OPENMP)
|
||||
size_t i = omp_get_thread_num();
|
||||
#endif
|
||||
size_t inlen__ = inlen;
|
||||
const unsigned char *in__ = ( const unsigned char * )in;
|
||||
in__ += i * BLAKE2B_BLOCKBYTES;
|
||||
|
||||
while( inlen__ >= PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES )
|
||||
{
|
||||
blake2b_update( S[i], in__, BLAKE2B_BLOCKBYTES );
|
||||
in__ += PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES;
|
||||
inlen__ -= PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES;
|
||||
}
|
||||
|
||||
if( inlen__ > i * BLAKE2B_BLOCKBYTES )
|
||||
{
|
||||
const size_t left = inlen__ - i * BLAKE2B_BLOCKBYTES;
|
||||
const size_t len = left <= BLAKE2B_BLOCKBYTES ? left : BLAKE2B_BLOCKBYTES;
|
||||
blake2b_update( S[i], in__, len );
|
||||
}
|
||||
|
||||
blake2b_final( S[i], hash[i], BLAKE2B_OUTBYTES );
|
||||
}
|
||||
|
||||
if( blake2bp_init_root( FS, outlen, keylen ) < 0 )
|
||||
return -1;
|
||||
|
||||
FS->last_node = 1; /* Mark as last node */
|
||||
|
||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||
blake2b_update( FS, hash[i], BLAKE2B_OUTBYTES );
|
||||
|
||||
return blake2b_final( FS, out, outlen );;
|
||||
}
|
||||
|
||||
#if defined(BLAKE2BP_SELFTEST)
|
||||
#include <string.h>
|
||||
#include "blake2-kat.h"
|
||||
int main( void )
|
||||
{
|
||||
uint8_t key[BLAKE2B_KEYBYTES];
|
||||
uint8_t buf[BLAKE2_KAT_LENGTH];
|
||||
size_t i, step;
|
||||
|
||||
for( i = 0; i < BLAKE2B_KEYBYTES; ++i )
|
||||
key[i] = ( uint8_t )i;
|
||||
|
||||
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
|
||||
buf[i] = ( uint8_t )i;
|
||||
|
||||
/* Test simple API */
|
||||
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
|
||||
{
|
||||
uint8_t hash[BLAKE2B_OUTBYTES];
|
||||
blake2bp( hash, BLAKE2B_OUTBYTES, buf, i, key, BLAKE2B_KEYBYTES );
|
||||
|
||||
if( 0 != memcmp( hash, blake2bp_keyed_kat[i], BLAKE2B_OUTBYTES ) )
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* Test streaming API */
|
||||
for(step = 1; step < BLAKE2B_BLOCKBYTES; ++step) {
|
||||
for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) {
|
||||
uint8_t hash[BLAKE2B_OUTBYTES];
|
||||
blake2bp_state S;
|
||||
uint8_t * p = buf;
|
||||
size_t mlen = i;
|
||||
int err = 0;
|
||||
|
||||
if( (err = blake2bp_init_key(&S, BLAKE2B_OUTBYTES, key, BLAKE2B_KEYBYTES)) < 0 ) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
while (mlen >= step) {
|
||||
if ( (err = blake2bp_update(&S, p, step)) < 0 ) {
|
||||
goto fail;
|
||||
}
|
||||
mlen -= step;
|
||||
p += step;
|
||||
}
|
||||
if ( (err = blake2bp_update(&S, p, mlen)) < 0) {
|
||||
goto fail;
|
||||
}
|
||||
if ( (err = blake2bp_final(&S, hash, BLAKE2B_OUTBYTES)) < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (0 != memcmp(hash, blake2bp_keyed_kat[i], BLAKE2B_OUTBYTES)) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
puts( "ok" );
|
||||
return 0;
|
||||
fail:
|
||||
puts("error");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
@@ -1,367 +0,0 @@
|
||||
/*
|
||||
BLAKE2 reference source code package - reference C implementations
|
||||
|
||||
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
|
||||
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
|
||||
your option. The terms of these licenses can be found at:
|
||||
|
||||
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
|
||||
- OpenSSL license : https://www.openssl.org/source/license.html
|
||||
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
More information about the BLAKE2 hash function can be found at
|
||||
https://blake2.net.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "blake2.h"
|
||||
#include "blake2-impl.h"
|
||||
|
||||
static const uint32_t blake2s_IV[8] =
|
||||
{
|
||||
0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL,
|
||||
0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL
|
||||
};
|
||||
|
||||
static const uint8_t blake2s_sigma[10][16] =
|
||||
{
|
||||
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
|
||||
{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } ,
|
||||
{ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } ,
|
||||
{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } ,
|
||||
{ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } ,
|
||||
{ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } ,
|
||||
{ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } ,
|
||||
{ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } ,
|
||||
{ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } ,
|
||||
{ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } ,
|
||||
};
|
||||
|
||||
static void blake2s_set_lastnode( blake2s_state *S )
|
||||
{
|
||||
S->f[1] = (uint32_t)-1;
|
||||
}
|
||||
|
||||
/* Some helper functions, not necessarily useful */
|
||||
static int blake2s_is_lastblock( const blake2s_state *S )
|
||||
{
|
||||
return S->f[0] != 0;
|
||||
}
|
||||
|
||||
static void blake2s_set_lastblock( blake2s_state *S )
|
||||
{
|
||||
if( S->last_node ) blake2s_set_lastnode( S );
|
||||
|
||||
S->f[0] = (uint32_t)-1;
|
||||
}
|
||||
|
||||
static void blake2s_increment_counter( blake2s_state *S, const uint32_t inc )
|
||||
{
|
||||
S->t[0] += inc;
|
||||
S->t[1] += ( S->t[0] < inc );
|
||||
}
|
||||
|
||||
static void blake2s_init0( blake2s_state *S )
|
||||
{
|
||||
size_t i;
|
||||
memset( S, 0, sizeof( blake2s_state ) );
|
||||
|
||||
for( i = 0; i < 8; ++i ) S->h[i] = blake2s_IV[i];
|
||||
}
|
||||
|
||||
/* init2 xors IV with input parameter block */
|
||||
int blake2s_init_param( blake2s_state *S, const blake2s_param *P )
|
||||
{
|
||||
const unsigned char *p = ( const unsigned char * )( P );
|
||||
size_t i;
|
||||
|
||||
blake2s_init0( S );
|
||||
|
||||
/* IV XOR ParamBlock */
|
||||
for( i = 0; i < 8; ++i )
|
||||
S->h[i] ^= load32( &p[i * 4] );
|
||||
|
||||
S->outlen = P->digest_length;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Sequential blake2s initialization */
|
||||
int blake2s_init( blake2s_state *S, size_t outlen )
|
||||
{
|
||||
blake2s_param P[1];
|
||||
|
||||
/* Move interval verification here? */
|
||||
if ( ( !outlen ) || ( outlen > BLAKE2S_OUTBYTES ) ) return -1;
|
||||
|
||||
P->digest_length = (uint8_t)outlen;
|
||||
P->key_length = 0;
|
||||
P->fanout = 1;
|
||||
P->depth = 1;
|
||||
store32( &P->leaf_length, 0 );
|
||||
store32( &P->node_offset, 0 );
|
||||
store16( &P->xof_length, 0 );
|
||||
P->node_depth = 0;
|
||||
P->inner_length = 0;
|
||||
/* memset(P->reserved, 0, sizeof(P->reserved) ); */
|
||||
memset( P->salt, 0, sizeof( P->salt ) );
|
||||
memset( P->personal, 0, sizeof( P->personal ) );
|
||||
return blake2s_init_param( S, P );
|
||||
}
|
||||
|
||||
int blake2s_init_key( blake2s_state *S, size_t outlen, const void *key, size_t keylen )
|
||||
{
|
||||
blake2s_param P[1];
|
||||
|
||||
if ( ( !outlen ) || ( outlen > BLAKE2S_OUTBYTES ) ) return -1;
|
||||
|
||||
if ( !key || !keylen || keylen > BLAKE2S_KEYBYTES ) return -1;
|
||||
|
||||
P->digest_length = (uint8_t)outlen;
|
||||
P->key_length = (uint8_t)keylen;
|
||||
P->fanout = 1;
|
||||
P->depth = 1;
|
||||
store32( &P->leaf_length, 0 );
|
||||
store32( &P->node_offset, 0 );
|
||||
store16( &P->xof_length, 0 );
|
||||
P->node_depth = 0;
|
||||
P->inner_length = 0;
|
||||
/* memset(P->reserved, 0, sizeof(P->reserved) ); */
|
||||
memset( P->salt, 0, sizeof( P->salt ) );
|
||||
memset( P->personal, 0, sizeof( P->personal ) );
|
||||
|
||||
if( blake2s_init_param( S, P ) < 0 ) return -1;
|
||||
|
||||
{
|
||||
uint8_t block[BLAKE2S_BLOCKBYTES];
|
||||
memset( block, 0, BLAKE2S_BLOCKBYTES );
|
||||
memcpy( block, key, keylen );
|
||||
blake2s_update( S, block, BLAKE2S_BLOCKBYTES );
|
||||
secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define G(r,i,a,b,c,d) \
|
||||
do { \
|
||||
a = a + b + m[blake2s_sigma[r][2*i+0]]; \
|
||||
d = rotr32(d ^ a, 16); \
|
||||
c = c + d; \
|
||||
b = rotr32(b ^ c, 12); \
|
||||
a = a + b + m[blake2s_sigma[r][2*i+1]]; \
|
||||
d = rotr32(d ^ a, 8); \
|
||||
c = c + d; \
|
||||
b = rotr32(b ^ c, 7); \
|
||||
} while(0)
|
||||
|
||||
#define ROUND(r) \
|
||||
do { \
|
||||
G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \
|
||||
G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \
|
||||
G(r,2,v[ 2],v[ 6],v[10],v[14]); \
|
||||
G(r,3,v[ 3],v[ 7],v[11],v[15]); \
|
||||
G(r,4,v[ 0],v[ 5],v[10],v[15]); \
|
||||
G(r,5,v[ 1],v[ 6],v[11],v[12]); \
|
||||
G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \
|
||||
G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \
|
||||
} while(0)
|
||||
|
||||
static void blake2s_compress( blake2s_state *S, const uint8_t in[BLAKE2S_BLOCKBYTES] )
|
||||
{
|
||||
uint32_t m[16];
|
||||
uint32_t v[16];
|
||||
size_t i;
|
||||
|
||||
for( i = 0; i < 16; ++i ) {
|
||||
m[i] = load32( in + i * sizeof( m[i] ) );
|
||||
}
|
||||
|
||||
for( i = 0; i < 8; ++i ) {
|
||||
v[i] = S->h[i];
|
||||
}
|
||||
|
||||
v[ 8] = blake2s_IV[0];
|
||||
v[ 9] = blake2s_IV[1];
|
||||
v[10] = blake2s_IV[2];
|
||||
v[11] = blake2s_IV[3];
|
||||
v[12] = S->t[0] ^ blake2s_IV[4];
|
||||
v[13] = S->t[1] ^ blake2s_IV[5];
|
||||
v[14] = S->f[0] ^ blake2s_IV[6];
|
||||
v[15] = S->f[1] ^ blake2s_IV[7];
|
||||
|
||||
ROUND( 0 );
|
||||
ROUND( 1 );
|
||||
ROUND( 2 );
|
||||
ROUND( 3 );
|
||||
ROUND( 4 );
|
||||
ROUND( 5 );
|
||||
ROUND( 6 );
|
||||
ROUND( 7 );
|
||||
ROUND( 8 );
|
||||
ROUND( 9 );
|
||||
|
||||
for( i = 0; i < 8; ++i ) {
|
||||
S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
|
||||
}
|
||||
}
|
||||
|
||||
#undef G
|
||||
#undef ROUND
|
||||
|
||||
int blake2s_update( blake2s_state *S, const void *pin, size_t inlen )
|
||||
{
|
||||
const unsigned char * in = (const unsigned char *)pin;
|
||||
if( inlen > 0 )
|
||||
{
|
||||
size_t left = S->buflen;
|
||||
size_t fill = BLAKE2S_BLOCKBYTES - left;
|
||||
if( inlen > fill )
|
||||
{
|
||||
S->buflen = 0;
|
||||
memcpy( S->buf + left, in, fill ); /* Fill buffer */
|
||||
blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES );
|
||||
blake2s_compress( S, S->buf ); /* Compress */
|
||||
in += fill; inlen -= fill;
|
||||
while(inlen > BLAKE2S_BLOCKBYTES) {
|
||||
blake2s_increment_counter(S, BLAKE2S_BLOCKBYTES);
|
||||
blake2s_compress( S, in );
|
||||
in += BLAKE2S_BLOCKBYTES;
|
||||
inlen -= BLAKE2S_BLOCKBYTES;
|
||||
}
|
||||
}
|
||||
memcpy( S->buf + S->buflen, in, inlen );
|
||||
S->buflen += inlen;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blake2s_final( blake2s_state *S, void *out, size_t outlen )
|
||||
{
|
||||
uint8_t buffer[BLAKE2S_OUTBYTES] = {0};
|
||||
size_t i;
|
||||
|
||||
if( out == NULL || outlen < S->outlen )
|
||||
return -1;
|
||||
|
||||
if( blake2s_is_lastblock( S ) )
|
||||
return -1;
|
||||
|
||||
blake2s_increment_counter( S, ( uint32_t )S->buflen );
|
||||
blake2s_set_lastblock( S );
|
||||
memset( S->buf + S->buflen, 0, BLAKE2S_BLOCKBYTES - S->buflen ); /* Padding */
|
||||
blake2s_compress( S, S->buf );
|
||||
|
||||
for( i = 0; i < 8; ++i ) /* Output full hash to temp buffer */
|
||||
store32( buffer + sizeof( S->h[i] ) * i, S->h[i] );
|
||||
|
||||
memcpy( out, buffer, outlen );
|
||||
secure_zero_memory(buffer, sizeof(buffer));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blake2s( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )
|
||||
{
|
||||
blake2s_state S[1];
|
||||
|
||||
/* Verify parameters */
|
||||
if ( NULL == in && inlen > 0 ) return -1;
|
||||
|
||||
if ( NULL == out ) return -1;
|
||||
|
||||
if ( NULL == key && keylen > 0) return -1;
|
||||
|
||||
if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;
|
||||
|
||||
if( keylen > BLAKE2S_KEYBYTES ) return -1;
|
||||
|
||||
if( keylen > 0 )
|
||||
{
|
||||
if( blake2s_init_key( S, outlen, key, keylen ) < 0 ) return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( blake2s_init( S, outlen ) < 0 ) return -1;
|
||||
}
|
||||
|
||||
blake2s_update( S, ( const uint8_t * )in, inlen );
|
||||
blake2s_final( S, out, outlen );
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(SUPERCOP)
|
||||
int crypto_hash( unsigned char *out, unsigned char *in, unsigned long long inlen )
|
||||
{
|
||||
return blake2s( out, BLAKE2S_OUTBYTES, in, inlen, NULL, 0 );
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(BLAKE2S_SELFTEST)
|
||||
#include <string.h>
|
||||
#include "blake2-kat.h"
|
||||
int main( void )
|
||||
{
|
||||
uint8_t key[BLAKE2S_KEYBYTES];
|
||||
uint8_t buf[BLAKE2_KAT_LENGTH];
|
||||
size_t i, step;
|
||||
|
||||
for( i = 0; i < BLAKE2S_KEYBYTES; ++i )
|
||||
key[i] = ( uint8_t )i;
|
||||
|
||||
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
|
||||
buf[i] = ( uint8_t )i;
|
||||
|
||||
/* Test simple API */
|
||||
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
|
||||
{
|
||||
uint8_t hash[BLAKE2S_OUTBYTES];
|
||||
blake2s( hash, BLAKE2S_OUTBYTES, buf, i, key, BLAKE2S_KEYBYTES );
|
||||
|
||||
if( 0 != memcmp( hash, blake2s_keyed_kat[i], BLAKE2S_OUTBYTES ) )
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* Test streaming API */
|
||||
for(step = 1; step < BLAKE2S_BLOCKBYTES; ++step) {
|
||||
for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) {
|
||||
uint8_t hash[BLAKE2S_OUTBYTES];
|
||||
blake2s_state S;
|
||||
uint8_t * p = buf;
|
||||
size_t mlen = i;
|
||||
int err = 0;
|
||||
|
||||
if( (err = blake2s_init_key(&S, BLAKE2S_OUTBYTES, key, BLAKE2S_KEYBYTES)) < 0 ) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
while (mlen >= step) {
|
||||
if ( (err = blake2s_update(&S, p, step)) < 0 ) {
|
||||
goto fail;
|
||||
}
|
||||
mlen -= step;
|
||||
p += step;
|
||||
}
|
||||
if ( (err = blake2s_update(&S, p, mlen)) < 0) {
|
||||
goto fail;
|
||||
}
|
||||
if ( (err = blake2s_final(&S, hash, BLAKE2S_OUTBYTES)) < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (0 != memcmp(hash, blake2s_keyed_kat[i], BLAKE2S_OUTBYTES)) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
puts( "ok" );
|
||||
return 0;
|
||||
fail:
|
||||
puts("error");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
@@ -1,359 +0,0 @@
|
||||
/*
|
||||
BLAKE2 reference source code package - reference C implementations
|
||||
|
||||
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
|
||||
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
|
||||
your option. The terms of these licenses can be found at:
|
||||
|
||||
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
|
||||
- OpenSSL license : https://www.openssl.org/source/license.html
|
||||
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
More information about the BLAKE2 hash function can be found at
|
||||
https://blake2.net.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#include <omp.h>
|
||||
#endif
|
||||
|
||||
#include "blake2.h"
|
||||
#include "blake2-impl.h"
|
||||
|
||||
#define PARALLELISM_DEGREE 8
|
||||
|
||||
/*
|
||||
blake2sp_init_param defaults to setting the expecting output length
|
||||
from the digest_length parameter block field.
|
||||
|
||||
In some cases, however, we do not want this, as the output length
|
||||
of these instances is given by inner_length instead.
|
||||
*/
|
||||
static int blake2sp_init_leaf_param( blake2s_state *S, const blake2s_param *P )
|
||||
{
|
||||
int err = blake2s_init_param(S, P);
|
||||
S->outlen = P->inner_length;
|
||||
return err;
|
||||
}
|
||||
|
||||
static int blake2sp_init_leaf( blake2s_state *S, size_t outlen, size_t keylen, uint64_t offset )
|
||||
{
|
||||
blake2s_param P[1];
|
||||
P->digest_length = (uint8_t)outlen;
|
||||
P->key_length = (uint8_t)keylen;
|
||||
P->fanout = PARALLELISM_DEGREE;
|
||||
P->depth = 2;
|
||||
store32( &P->leaf_length, 0 );
|
||||
store32( &P->node_offset, offset );
|
||||
store16( &P->xof_length, 0 );
|
||||
P->node_depth = 0;
|
||||
P->inner_length = BLAKE2S_OUTBYTES;
|
||||
memset( P->salt, 0, sizeof( P->salt ) );
|
||||
memset( P->personal, 0, sizeof( P->personal ) );
|
||||
return blake2sp_init_leaf_param( S, P );
|
||||
}
|
||||
|
||||
static int blake2sp_init_root( blake2s_state *S, size_t outlen, size_t keylen )
|
||||
{
|
||||
blake2s_param P[1];
|
||||
P->digest_length = (uint8_t)outlen;
|
||||
P->key_length = (uint8_t)keylen;
|
||||
P->fanout = PARALLELISM_DEGREE;
|
||||
P->depth = 2;
|
||||
store32( &P->leaf_length, 0 );
|
||||
store32( &P->node_offset, 0 );
|
||||
store16( &P->xof_length, 0 );
|
||||
P->node_depth = 1;
|
||||
P->inner_length = BLAKE2S_OUTBYTES;
|
||||
memset( P->salt, 0, sizeof( P->salt ) );
|
||||
memset( P->personal, 0, sizeof( P->personal ) );
|
||||
return blake2s_init_param( S, P );
|
||||
}
|
||||
|
||||
|
||||
int blake2sp_init( blake2sp_state *S, size_t outlen )
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;
|
||||
|
||||
memset( S->buf, 0, sizeof( S->buf ) );
|
||||
S->buflen = 0;
|
||||
S->outlen = outlen;
|
||||
|
||||
if( blake2sp_init_root( S->R, outlen, 0 ) < 0 )
|
||||
return -1;
|
||||
|
||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||
if( blake2sp_init_leaf( S->S[i], outlen, 0, i ) < 0 ) return -1;
|
||||
|
||||
S->R->last_node = 1;
|
||||
S->S[PARALLELISM_DEGREE - 1]->last_node = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blake2sp_init_key( blake2sp_state *S, size_t outlen, const void *key, size_t keylen )
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;
|
||||
|
||||
if( !key || !keylen || keylen > BLAKE2S_KEYBYTES ) return -1;
|
||||
|
||||
memset( S->buf, 0, sizeof( S->buf ) );
|
||||
S->buflen = 0;
|
||||
S->outlen = outlen;
|
||||
|
||||
if( blake2sp_init_root( S->R, outlen, keylen ) < 0 )
|
||||
return -1;
|
||||
|
||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||
if( blake2sp_init_leaf( S->S[i], outlen, keylen, i ) < 0 ) return -1;
|
||||
|
||||
S->R->last_node = 1;
|
||||
S->S[PARALLELISM_DEGREE - 1]->last_node = 1;
|
||||
{
|
||||
uint8_t block[BLAKE2S_BLOCKBYTES];
|
||||
memset( block, 0, BLAKE2S_BLOCKBYTES );
|
||||
memcpy( block, key, keylen );
|
||||
|
||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||
blake2s_update( S->S[i], block, BLAKE2S_BLOCKBYTES );
|
||||
|
||||
secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int blake2sp_update( blake2sp_state *S, const void *pin, size_t inlen )
|
||||
{
|
||||
const unsigned char * in = (const unsigned char *)pin;
|
||||
size_t left = S->buflen;
|
||||
size_t fill = sizeof( S->buf ) - left;
|
||||
size_t i;
|
||||
|
||||
if( left && inlen >= fill )
|
||||
{
|
||||
memcpy( S->buf + left, in, fill );
|
||||
|
||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||
blake2s_update( S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, BLAKE2S_BLOCKBYTES );
|
||||
|
||||
in += fill;
|
||||
inlen -= fill;
|
||||
left = 0;
|
||||
}
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel shared(S), num_threads(PARALLELISM_DEGREE)
|
||||
#else
|
||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||
#endif
|
||||
{
|
||||
#if defined(_OPENMP)
|
||||
size_t i = omp_get_thread_num();
|
||||
#endif
|
||||
size_t inlen__ = inlen;
|
||||
const unsigned char *in__ = ( const unsigned char * )in;
|
||||
in__ += i * BLAKE2S_BLOCKBYTES;
|
||||
|
||||
while( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES )
|
||||
{
|
||||
blake2s_update( S->S[i], in__, BLAKE2S_BLOCKBYTES );
|
||||
in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
|
||||
inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
|
||||
}
|
||||
}
|
||||
|
||||
in += inlen - inlen % ( PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES );
|
||||
inlen %= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
|
||||
|
||||
if( inlen > 0 )
|
||||
memcpy( S->buf + left, in, inlen );
|
||||
|
||||
S->buflen = left + inlen;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int blake2sp_final( blake2sp_state *S, void *out, size_t outlen )
|
||||
{
|
||||
uint8_t hash[PARALLELISM_DEGREE][BLAKE2S_OUTBYTES];
|
||||
size_t i;
|
||||
|
||||
if(out == NULL || outlen < S->outlen) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||
{
|
||||
if( S->buflen > i * BLAKE2S_BLOCKBYTES )
|
||||
{
|
||||
size_t left = S->buflen - i * BLAKE2S_BLOCKBYTES;
|
||||
|
||||
if( left > BLAKE2S_BLOCKBYTES ) left = BLAKE2S_BLOCKBYTES;
|
||||
|
||||
blake2s_update( S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, left );
|
||||
}
|
||||
|
||||
blake2s_final( S->S[i], hash[i], BLAKE2S_OUTBYTES );
|
||||
}
|
||||
|
||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||
blake2s_update( S->R, hash[i], BLAKE2S_OUTBYTES );
|
||||
|
||||
return blake2s_final( S->R, out, S->outlen );
|
||||
}
|
||||
|
||||
|
||||
int blake2sp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )
|
||||
{
|
||||
uint8_t hash[PARALLELISM_DEGREE][BLAKE2S_OUTBYTES];
|
||||
blake2s_state S[PARALLELISM_DEGREE][1];
|
||||
blake2s_state FS[1];
|
||||
size_t i;
|
||||
|
||||
/* Verify parameters */
|
||||
if ( NULL == in && inlen > 0 ) return -1;
|
||||
|
||||
if ( NULL == out ) return -1;
|
||||
|
||||
if ( NULL == key && keylen > 0) return -1;
|
||||
|
||||
if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;
|
||||
|
||||
if( keylen > BLAKE2S_KEYBYTES ) return -1;
|
||||
|
||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||
if( blake2sp_init_leaf( S[i], outlen, keylen, i ) < 0 ) return -1;
|
||||
|
||||
S[PARALLELISM_DEGREE - 1]->last_node = 1; /* mark last node */
|
||||
|
||||
if( keylen > 0 )
|
||||
{
|
||||
uint8_t block[BLAKE2S_BLOCKBYTES];
|
||||
memset( block, 0, BLAKE2S_BLOCKBYTES );
|
||||
memcpy( block, key, keylen );
|
||||
|
||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||
blake2s_update( S[i], block, BLAKE2S_BLOCKBYTES );
|
||||
|
||||
secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */
|
||||
}
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel shared(S,hash), num_threads(PARALLELISM_DEGREE)
|
||||
#else
|
||||
|
||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||
#endif
|
||||
{
|
||||
#if defined(_OPENMP)
|
||||
size_t i = omp_get_thread_num();
|
||||
#endif
|
||||
size_t inlen__ = inlen;
|
||||
const unsigned char *in__ = ( const unsigned char * )in;
|
||||
in__ += i * BLAKE2S_BLOCKBYTES;
|
||||
|
||||
while( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES )
|
||||
{
|
||||
blake2s_update( S[i], in__, BLAKE2S_BLOCKBYTES );
|
||||
in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
|
||||
inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
|
||||
}
|
||||
|
||||
if( inlen__ > i * BLAKE2S_BLOCKBYTES )
|
||||
{
|
||||
const size_t left = inlen__ - i * BLAKE2S_BLOCKBYTES;
|
||||
const size_t len = left <= BLAKE2S_BLOCKBYTES ? left : BLAKE2S_BLOCKBYTES;
|
||||
blake2s_update( S[i], in__, len );
|
||||
}
|
||||
|
||||
blake2s_final( S[i], hash[i], BLAKE2S_OUTBYTES );
|
||||
}
|
||||
|
||||
if( blake2sp_init_root( FS, outlen, keylen ) < 0 )
|
||||
return -1;
|
||||
|
||||
FS->last_node = 1;
|
||||
|
||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||
blake2s_update( FS, hash[i], BLAKE2S_OUTBYTES );
|
||||
|
||||
return blake2s_final( FS, out, outlen );
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if defined(BLAKE2SP_SELFTEST)
|
||||
#include <string.h>
|
||||
#include "blake2-kat.h"
|
||||
int main( void )
|
||||
{
|
||||
uint8_t key[BLAKE2S_KEYBYTES];
|
||||
uint8_t buf[BLAKE2_KAT_LENGTH];
|
||||
size_t i, step;
|
||||
|
||||
for( i = 0; i < BLAKE2S_KEYBYTES; ++i )
|
||||
key[i] = ( uint8_t )i;
|
||||
|
||||
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
|
||||
buf[i] = ( uint8_t )i;
|
||||
|
||||
/* Test simple API */
|
||||
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
|
||||
{
|
||||
uint8_t hash[BLAKE2S_OUTBYTES];
|
||||
blake2sp( hash, BLAKE2S_OUTBYTES, buf, i, key, BLAKE2S_KEYBYTES );
|
||||
|
||||
if( 0 != memcmp( hash, blake2sp_keyed_kat[i], BLAKE2S_OUTBYTES ) )
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* Test streaming API */
|
||||
for(step = 1; step < BLAKE2S_BLOCKBYTES; ++step) {
|
||||
for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) {
|
||||
uint8_t hash[BLAKE2S_OUTBYTES];
|
||||
blake2sp_state S;
|
||||
uint8_t * p = buf;
|
||||
size_t mlen = i;
|
||||
int err = 0;
|
||||
|
||||
if( (err = blake2sp_init_key(&S, BLAKE2S_OUTBYTES, key, BLAKE2S_KEYBYTES)) < 0 ) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
while (mlen >= step) {
|
||||
if ( (err = blake2sp_update(&S, p, step)) < 0 ) {
|
||||
goto fail;
|
||||
}
|
||||
mlen -= step;
|
||||
p += step;
|
||||
}
|
||||
if ( (err = blake2sp_update(&S, p, mlen)) < 0) {
|
||||
goto fail;
|
||||
}
|
||||
if ( (err = blake2sp_final(&S, hash, BLAKE2S_OUTBYTES)) < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (0 != memcmp(hash, blake2sp_keyed_kat[i], BLAKE2S_OUTBYTES)) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
puts( "ok" );
|
||||
return 0;
|
||||
fail:
|
||||
puts("error");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
@@ -1,241 +0,0 @@
|
||||
/*
|
||||
BLAKE2 reference source code package - reference C implementations
|
||||
|
||||
Copyright 2016, JP Aumasson <jeanphilippe.aumasson@gmail.com>.
|
||||
Copyright 2016, Samuel Neves <sneves@dei.uc.pt>.
|
||||
|
||||
You may use this under the terms of the CC0, the OpenSSL Licence, or
|
||||
the Apache Public License 2.0, at your option. The terms of these
|
||||
licenses can be found at:
|
||||
|
||||
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
|
||||
- OpenSSL license : https://www.openssl.org/source/license.html
|
||||
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
More information about the BLAKE2 hash function can be found at
|
||||
https://blake2.net.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "blake2.h"
|
||||
#include "blake2-impl.h"
|
||||
|
||||
int blake2xb_init( blake2xb_state *S, const size_t outlen ) {
|
||||
return blake2xb_init_key(S, outlen, NULL, 0);
|
||||
}
|
||||
|
||||
int blake2xb_init_key( blake2xb_state *S, const size_t outlen, const void *key, size_t keylen)
|
||||
{
|
||||
if ( outlen == 0 || outlen > 0xFFFFFFFFUL ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (NULL != key && keylen > BLAKE2B_KEYBYTES) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (NULL == key && keylen > 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Initialize parameter block */
|
||||
S->P->digest_length = BLAKE2B_OUTBYTES;
|
||||
S->P->key_length = keylen;
|
||||
S->P->fanout = 1;
|
||||
S->P->depth = 1;
|
||||
store32( &S->P->leaf_length, 0 );
|
||||
store32( &S->P->node_offset, 0 );
|
||||
store32( &S->P->xof_length, outlen );
|
||||
S->P->node_depth = 0;
|
||||
S->P->inner_length = 0;
|
||||
memset( S->P->reserved, 0, sizeof( S->P->reserved ) );
|
||||
memset( S->P->salt, 0, sizeof( S->P->salt ) );
|
||||
memset( S->P->personal, 0, sizeof( S->P->personal ) );
|
||||
|
||||
if( blake2b_init_param( S->S, S->P ) < 0 ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (keylen > 0) {
|
||||
uint8_t block[BLAKE2B_BLOCKBYTES];
|
||||
memset(block, 0, BLAKE2B_BLOCKBYTES);
|
||||
memcpy(block, key, keylen);
|
||||
blake2b_update(S->S, block, BLAKE2B_BLOCKBYTES);
|
||||
secure_zero_memory(block, BLAKE2B_BLOCKBYTES);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blake2xb_update( blake2xb_state *S, const void *in, size_t inlen ) {
|
||||
return blake2b_update( S->S, in, inlen );
|
||||
}
|
||||
|
||||
int blake2xb_final( blake2xb_state *S, void *out, size_t outlen) {
|
||||
|
||||
blake2b_state C[1];
|
||||
blake2b_param P[1];
|
||||
uint32_t xof_length = load32(&S->P->xof_length);
|
||||
uint8_t root[BLAKE2B_BLOCKBYTES];
|
||||
size_t i;
|
||||
|
||||
if (NULL == out) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* outlen must match the output size defined in xof_length, */
|
||||
/* unless it was -1, in which case anything goes except 0. */
|
||||
if(xof_length == 0xFFFFFFFFUL) {
|
||||
if(outlen == 0) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if(outlen != xof_length) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Finalize the root hash */
|
||||
if (blake2b_final(S->S, root, BLAKE2B_OUTBYTES) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Set common block structure values */
|
||||
/* Copy values from parent instance, and only change the ones below */
|
||||
memcpy(P, S->P, sizeof(blake2b_param));
|
||||
P->key_length = 0;
|
||||
P->fanout = 0;
|
||||
P->depth = 0;
|
||||
store32(&P->leaf_length, BLAKE2B_OUTBYTES);
|
||||
P->inner_length = BLAKE2B_OUTBYTES;
|
||||
P->node_depth = 0;
|
||||
|
||||
for (i = 0; outlen > 0; ++i) {
|
||||
const size_t block_size = (outlen < BLAKE2B_OUTBYTES) ? outlen : BLAKE2B_OUTBYTES;
|
||||
/* Initialize state */
|
||||
P->digest_length = block_size;
|
||||
store32(&P->node_offset, i);
|
||||
blake2b_init_param(C, P);
|
||||
/* Process key if needed */
|
||||
blake2b_update(C, root, BLAKE2B_OUTBYTES);
|
||||
if (blake2b_final(C, (uint8_t *)out + i * BLAKE2B_OUTBYTES, block_size) < 0 ) {
|
||||
return -1;
|
||||
}
|
||||
outlen -= block_size;
|
||||
}
|
||||
secure_zero_memory(root, sizeof(root));
|
||||
secure_zero_memory(P, sizeof(P));
|
||||
secure_zero_memory(C, sizeof(C));
|
||||
/* Put blake2xb in an invalid state? cf. blake2s_is_lastblock */
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int blake2xb(void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen)
|
||||
{
|
||||
blake2xb_state S[1];
|
||||
|
||||
/* Verify parameters */
|
||||
if (NULL == in && inlen > 0)
|
||||
return -1;
|
||||
|
||||
if (NULL == out)
|
||||
return -1;
|
||||
|
||||
if (NULL == key && keylen > 0)
|
||||
return -1;
|
||||
|
||||
if (keylen > BLAKE2B_KEYBYTES)
|
||||
return -1;
|
||||
|
||||
if (outlen == 0)
|
||||
return -1;
|
||||
|
||||
/* Initialize the root block structure */
|
||||
if (blake2xb_init_key(S, outlen, key, keylen) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Absorb the input message */
|
||||
blake2xb_update(S, in, inlen);
|
||||
|
||||
/* Compute the root node of the tree and the final hash using the counter construction */
|
||||
return blake2xb_final(S, out, outlen);
|
||||
}
|
||||
|
||||
#if defined(BLAKE2XB_SELFTEST)
|
||||
#include <string.h>
|
||||
#include "blake2-kat.h"
|
||||
int main( void )
|
||||
{
|
||||
uint8_t key[BLAKE2B_KEYBYTES];
|
||||
uint8_t buf[BLAKE2_KAT_LENGTH];
|
||||
size_t i, step, outlen;
|
||||
|
||||
for( i = 0; i < BLAKE2B_KEYBYTES; ++i ) {
|
||||
key[i] = ( uint8_t )i;
|
||||
}
|
||||
|
||||
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i ) {
|
||||
buf[i] = ( uint8_t )i;
|
||||
}
|
||||
|
||||
/* Testing length of outputs rather than inputs */
|
||||
/* (Test of input lengths mostly covered by blake2b tests) */
|
||||
|
||||
/* Test simple API */
|
||||
for( outlen = 1; outlen <= BLAKE2_KAT_LENGTH; ++outlen )
|
||||
{
|
||||
uint8_t hash[BLAKE2_KAT_LENGTH] = {0};
|
||||
if( blake2xb( hash, outlen, buf, BLAKE2_KAT_LENGTH, key, BLAKE2B_KEYBYTES ) < 0 ) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if( 0 != memcmp( hash, blake2xb_keyed_kat[outlen-1], outlen ) )
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* Test streaming API */
|
||||
for(step = 1; step < BLAKE2B_BLOCKBYTES; ++step) {
|
||||
for (outlen = 1; outlen <= BLAKE2_KAT_LENGTH; ++outlen) {
|
||||
uint8_t hash[BLAKE2_KAT_LENGTH];
|
||||
blake2xb_state S;
|
||||
uint8_t * p = buf;
|
||||
size_t mlen = BLAKE2_KAT_LENGTH;
|
||||
int err = 0;
|
||||
|
||||
if( (err = blake2xb_init_key(&S, outlen, key, BLAKE2B_KEYBYTES)) < 0 ) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
while (mlen >= step) {
|
||||
if ( (err = blake2xb_update(&S, p, step)) < 0 ) {
|
||||
goto fail;
|
||||
}
|
||||
mlen -= step;
|
||||
p += step;
|
||||
}
|
||||
if ( (err = blake2xb_update(&S, p, mlen)) < 0) {
|
||||
goto fail;
|
||||
}
|
||||
if ( (err = blake2xb_final(&S, hash, outlen)) < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (0 != memcmp(hash, blake2xb_keyed_kat[outlen-1], outlen)) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
puts( "ok" );
|
||||
return 0;
|
||||
fail:
|
||||
puts("error");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
@@ -1,239 +0,0 @@
|
||||
/*
|
||||
BLAKE2 reference source code package - reference C implementations
|
||||
|
||||
Copyright 2016, JP Aumasson <jeanphilippe.aumasson@gmail.com>.
|
||||
Copyright 2016, Samuel Neves <sneves@dei.uc.pt>.
|
||||
|
||||
You may use this under the terms of the CC0, the OpenSSL Licence, or
|
||||
the Apache Public License 2.0, at your option. The terms of these
|
||||
licenses can be found at:
|
||||
|
||||
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
|
||||
- OpenSSL license : https://www.openssl.org/source/license.html
|
||||
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
More information about the BLAKE2 hash function can be found at
|
||||
https://blake2.net.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "blake2.h"
|
||||
#include "blake2-impl.h"
|
||||
|
||||
int blake2xs_init( blake2xs_state *S, const size_t outlen ) {
|
||||
return blake2xs_init_key(S, outlen, NULL, 0);
|
||||
}
|
||||
|
||||
int blake2xs_init_key( blake2xs_state *S, const size_t outlen, const void *key, size_t keylen )
|
||||
{
|
||||
if ( outlen == 0 || outlen > 0xFFFFUL ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (NULL != key && keylen > BLAKE2S_KEYBYTES) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (NULL == key && keylen > 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Initialize parameter block */
|
||||
S->P->digest_length = BLAKE2S_OUTBYTES;
|
||||
S->P->key_length = keylen;
|
||||
S->P->fanout = 1;
|
||||
S->P->depth = 1;
|
||||
store32( &S->P->leaf_length, 0 );
|
||||
store32( &S->P->node_offset, 0 );
|
||||
store16( &S->P->xof_length, outlen );
|
||||
S->P->node_depth = 0;
|
||||
S->P->inner_length = 0;
|
||||
memset( S->P->salt, 0, sizeof( S->P->salt ) );
|
||||
memset( S->P->personal, 0, sizeof( S->P->personal ) );
|
||||
|
||||
if( blake2s_init_param( S->S, S->P ) < 0 ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (keylen > 0) {
|
||||
uint8_t block[BLAKE2S_BLOCKBYTES];
|
||||
memset(block, 0, BLAKE2S_BLOCKBYTES);
|
||||
memcpy(block, key, keylen);
|
||||
blake2s_update(S->S, block, BLAKE2S_BLOCKBYTES);
|
||||
secure_zero_memory(block, BLAKE2S_BLOCKBYTES);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blake2xs_update( blake2xs_state *S, const void *in, size_t inlen ) {
|
||||
return blake2s_update( S->S, in, inlen );
|
||||
}
|
||||
|
||||
int blake2xs_final(blake2xs_state *S, void *out, size_t outlen) {
|
||||
|
||||
blake2s_state C[1];
|
||||
blake2s_param P[1];
|
||||
uint16_t xof_length = load16(&S->P->xof_length);
|
||||
uint8_t root[BLAKE2S_BLOCKBYTES];
|
||||
size_t i;
|
||||
|
||||
if (NULL == out) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* outlen must match the output size defined in xof_length, */
|
||||
/* unless it was -1, in which case anything goes except 0. */
|
||||
if(xof_length == 0xFFFFUL) {
|
||||
if(outlen == 0) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if(outlen != xof_length) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Finalize the root hash */
|
||||
if (blake2s_final(S->S, root, BLAKE2S_OUTBYTES) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Set common block structure values */
|
||||
/* Copy values from parent instance, and only change the ones below */
|
||||
memcpy(P, S->P, sizeof(blake2s_param));
|
||||
P->key_length = 0;
|
||||
P->fanout = 0;
|
||||
P->depth = 0;
|
||||
store32(&P->leaf_length, BLAKE2S_OUTBYTES);
|
||||
P->inner_length = BLAKE2S_OUTBYTES;
|
||||
P->node_depth = 0;
|
||||
|
||||
for (i = 0; outlen > 0; ++i) {
|
||||
const size_t block_size = (outlen < BLAKE2S_OUTBYTES) ? outlen : BLAKE2S_OUTBYTES;
|
||||
/* Initialize state */
|
||||
P->digest_length = block_size;
|
||||
store32(&P->node_offset, i);
|
||||
blake2s_init_param(C, P);
|
||||
/* Process key if needed */
|
||||
blake2s_update(C, root, BLAKE2S_OUTBYTES);
|
||||
if (blake2s_final(C, (uint8_t *)out + i * BLAKE2S_OUTBYTES, block_size) < 0) {
|
||||
return -1;
|
||||
}
|
||||
outlen -= block_size;
|
||||
}
|
||||
secure_zero_memory(root, sizeof(root));
|
||||
secure_zero_memory(P, sizeof(P));
|
||||
secure_zero_memory(C, sizeof(C));
|
||||
/* Put blake2xs in an invalid state? cf. blake2s_is_lastblock */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blake2xs(void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen)
|
||||
{
|
||||
blake2xs_state S[1];
|
||||
|
||||
/* Verify parameters */
|
||||
if (NULL == in && inlen > 0)
|
||||
return -1;
|
||||
|
||||
if (NULL == out)
|
||||
return -1;
|
||||
|
||||
if (NULL == key && keylen > 0)
|
||||
return -1;
|
||||
|
||||
if (keylen > BLAKE2S_KEYBYTES)
|
||||
return -1;
|
||||
|
||||
if (outlen == 0)
|
||||
return -1;
|
||||
|
||||
/* Initialize the root block structure */
|
||||
if (blake2xs_init_key(S, outlen, key, keylen) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Absorb the input message */
|
||||
blake2xs_update(S, in, inlen);
|
||||
|
||||
/* Compute the root node of the tree and the final hash using the counter construction */
|
||||
return blake2xs_final(S, out, outlen);
|
||||
}
|
||||
|
||||
#if defined(BLAKE2XS_SELFTEST)
|
||||
#include <string.h>
|
||||
#include "blake2-kat.h"
|
||||
int main( void )
|
||||
{
|
||||
uint8_t key[BLAKE2S_KEYBYTES];
|
||||
uint8_t buf[BLAKE2_KAT_LENGTH];
|
||||
size_t i, step, outlen;
|
||||
|
||||
for( i = 0; i < BLAKE2S_KEYBYTES; ++i ) {
|
||||
key[i] = ( uint8_t )i;
|
||||
}
|
||||
|
||||
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i ) {
|
||||
buf[i] = ( uint8_t )i;
|
||||
}
|
||||
|
||||
/* Testing length of outputs rather than inputs */
|
||||
/* (Test of input lengths mostly covered by blake2s tests) */
|
||||
|
||||
/* Test simple API */
|
||||
for( outlen = 1; outlen <= BLAKE2_KAT_LENGTH; ++outlen )
|
||||
{
|
||||
uint8_t hash[BLAKE2_KAT_LENGTH] = {0};
|
||||
if( blake2xs( hash, outlen, buf, BLAKE2_KAT_LENGTH, key, BLAKE2S_KEYBYTES ) < 0 ) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if( 0 != memcmp( hash, blake2xs_keyed_kat[outlen-1], outlen ) )
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* Test streaming API */
|
||||
for(step = 1; step < BLAKE2S_BLOCKBYTES; ++step) {
|
||||
for (outlen = 1; outlen <= BLAKE2_KAT_LENGTH; ++outlen) {
|
||||
uint8_t hash[BLAKE2_KAT_LENGTH];
|
||||
blake2xs_state S;
|
||||
uint8_t * p = buf;
|
||||
size_t mlen = BLAKE2_KAT_LENGTH;
|
||||
int err = 0;
|
||||
|
||||
if( (err = blake2xs_init_key(&S, outlen, key, BLAKE2S_KEYBYTES)) < 0 ) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
while (mlen >= step) {
|
||||
if ( (err = blake2xs_update(&S, p, step)) < 0 ) {
|
||||
goto fail;
|
||||
}
|
||||
mlen -= step;
|
||||
p += step;
|
||||
}
|
||||
if ( (err = blake2xs_update(&S, p, mlen)) < 0) {
|
||||
goto fail;
|
||||
}
|
||||
if ( (err = blake2xs_final(&S, hash, outlen)) < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (0 != memcmp(hash, blake2xs_keyed_kat[outlen-1], outlen)) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
puts( "ok" );
|
||||
return 0;
|
||||
fail:
|
||||
puts("error");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
152
3rd/libzmq/AUTHORS
Normal file
152
3rd/libzmq/AUTHORS
Normal file
@@ -0,0 +1,152 @@
|
||||
Corporate Contributors
|
||||
======================
|
||||
|
||||
Copyright (c) 2007-2014 iMatix Corporation
|
||||
Copyright (c) 2009-2011 250bpm s.r.o.
|
||||
Copyright (c) 2010-2011 Miru Limited
|
||||
Copyright (c) 2011 VMware, Inc.
|
||||
Copyright (c) 2012 Spotify AB
|
||||
Copyright (c) 2013 Ericsson AB
|
||||
Copyright (c) 2014 AppDynamics Inc.
|
||||
Copyright (c) 2015 Google, Inc.
|
||||
Copyright (c) 2015-2016 Brocade Communications Systems Inc.
|
||||
|
||||
Individual Contributors
|
||||
=======================
|
||||
|
||||
AJ Lewis
|
||||
Alexej Lotz
|
||||
Andrew Thompson
|
||||
André Caron
|
||||
Asko Kauppi
|
||||
Attila Mark
|
||||
Barak Amar
|
||||
Ben Gray
|
||||
Bernd Melchers
|
||||
Bernd Prager
|
||||
Bob Beaty
|
||||
Brandon Carpenter
|
||||
Brett Cameron
|
||||
Brian Buchanan
|
||||
Burak Arslan
|
||||
Carl Clemens
|
||||
Chia-liang Kao
|
||||
Chris Busbey
|
||||
Chris Rempel
|
||||
Chris Wong
|
||||
Christian Gudrian
|
||||
Christian Kamm
|
||||
Chuck Remes
|
||||
Conrad D. Steenberg
|
||||
Constantin Rack
|
||||
Daniel J. Bernstein
|
||||
Dhammika Pathirana
|
||||
Dhruva Krishnamurthy
|
||||
Dirk O. Kaar
|
||||
Doron Somech
|
||||
Douglas Creager
|
||||
Drew Crawford
|
||||
Erich Heine
|
||||
Erik Hugne
|
||||
Erik Rigtorp
|
||||
Fabien Ninoles
|
||||
Frank Denis
|
||||
George Neill
|
||||
Gerard Toonstra
|
||||
Ghislain Putois
|
||||
Gonzalo Diethelm
|
||||
Guido Goldstein
|
||||
Harald Achitz
|
||||
Hardeep Singh
|
||||
Hiten Pandya
|
||||
Ian Barber
|
||||
Ilja Golshtein
|
||||
Ilya Kulakov
|
||||
Ivo Danihelka
|
||||
Jacob Rideout
|
||||
Joe Thornber
|
||||
Jon Dyte
|
||||
Kamil Shakirov
|
||||
Ken Steele
|
||||
Kouhei Sutou
|
||||
Laurent Alebarde
|
||||
Leonardo J. Consoni
|
||||
Lionel Flandrin
|
||||
Lourens Naudé
|
||||
Luca Boccassi
|
||||
Marc Rossi
|
||||
Mark Barbisan
|
||||
Martin Hurton
|
||||
Martin Lucina
|
||||
Martin Pales
|
||||
Martin Sustrik
|
||||
Matus Hamorsky
|
||||
Max Wolf
|
||||
McClain Looney
|
||||
Michael Compton
|
||||
Mika Fischer
|
||||
Mikael Helbo Kjaer
|
||||
Mike Gatny
|
||||
Mikko Koppanen
|
||||
Min Ragan-Kelley
|
||||
Neale Ferguson
|
||||
Nir Soffer
|
||||
Osiris Pedroso
|
||||
Paul Betts
|
||||
Paul Colomiets
|
||||
Pavel Gushcha
|
||||
Pavol Malosek
|
||||
Perry Kundert
|
||||
Peter Bourgon
|
||||
Philip Kovacs
|
||||
Pieter Hintjens
|
||||
Piotr Trojanek
|
||||
Reza Ebrahimi
|
||||
Richard Newton
|
||||
Rik van der Heijden
|
||||
Robert G. Jakabosky
|
||||
Sebastian Otaegui
|
||||
Stefan Radomski
|
||||
Steven McCoy
|
||||
Stuart Webster
|
||||
Tamara Kustarova
|
||||
Taras Shpot
|
||||
Tero Marttila
|
||||
Terry Wilson
|
||||
Thijs Terlouw
|
||||
Thomas Rodgers
|
||||
Tim Mossbarger
|
||||
Toralf Wittner
|
||||
Tore Halvorsen
|
||||
Trevor Bernard
|
||||
Vitaly Mayatskikh
|
||||
|
||||
Credits
|
||||
=======
|
||||
|
||||
Aamir Mohammad
|
||||
Adrian von Bidder
|
||||
Aleksey Yeschenko
|
||||
Alessio Spadaro
|
||||
Alexander Majorov
|
||||
Anh Vu
|
||||
Bernd Schumacher
|
||||
Brian Granger
|
||||
Carsten Dinkelmann
|
||||
David Bahi
|
||||
Dirk Eddelbuettel
|
||||
Evgueny Khartchenko
|
||||
Frank Vanden Berghen
|
||||
Ian Barber
|
||||
John Apps
|
||||
Markus Fischer
|
||||
Matt Muggeridge
|
||||
Michael Santy
|
||||
Oleg Sevostyanov
|
||||
Paulo Henrique Silva
|
||||
Peter Busser
|
||||
Peter Lemenkov
|
||||
Robert Zhang
|
||||
Toralf Wittner
|
||||
Zed Shaw
|
||||
|
||||
1813
3rd/libzmq/CMakeLists.txt
Normal file
1813
3rd/libzmq/CMakeLists.txt
Normal file
@@ -0,0 +1,1813 @@
|
||||
# CMake build script for ZeroMQ
|
||||
project(ZeroMQ)
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} STREQUAL Darwin)
|
||||
cmake_minimum_required(VERSION 3.0.2)
|
||||
else()
|
||||
cmake_minimum_required(VERSION 2.8.12)
|
||||
endif()
|
||||
|
||||
include(CheckIncludeFiles)
|
||||
include(CheckCCompilerFlag)
|
||||
include(CheckCXXCompilerFlag)
|
||||
include(CheckLibraryExists)
|
||||
include(CheckCSourceCompiles)
|
||||
include(CheckCSourceRuns)
|
||||
include(CMakeDependentOption)
|
||||
include(CheckCXXSymbolExists)
|
||||
include(CheckTypeSize)
|
||||
include(FindThreads)
|
||||
include(GNUInstallDirs)
|
||||
include(CheckTypeSize)
|
||||
include(CMakePackageConfigHelpers)
|
||||
|
||||
list(INSERT CMAKE_MODULE_PATH 0 "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
set(ZMQ_CMAKE_MODULES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/builds/cmake/Modules)
|
||||
list(APPEND CMAKE_MODULE_PATH ${ZMQ_CMAKE_MODULES_DIR})
|
||||
|
||||
include(TestZMQVersion)
|
||||
include(ZMQSourceRunChecks)
|
||||
include(ZMQSupportMacros)
|
||||
|
||||
find_package(PkgConfig)
|
||||
|
||||
# Set lists to empty beforehand as to not accidentally take values from parent
|
||||
set(sources)
|
||||
set(cxx-sources)
|
||||
set(html-docs)
|
||||
set(target_outputs)
|
||||
|
||||
option(ENABLE_ASAN "Build with address sanitizer" OFF)
|
||||
if(ENABLE_ASAN)
|
||||
message(STATUS "Instrumenting with Address Sanitizer")
|
||||
set(CMAKE_BUILD_TYPE "RelWithDebInfo")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fsanitize-address-use-after-scope -fno-omit-frame-pointer")
|
||||
set(CMAKE_CXX_FLAGS
|
||||
"${CMAKE_CXX_FLAGS} -fsanitize=address -fsanitize-address-use-after-scope -fno-omit-frame-pointer")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=address -fsanitize-address-use-after-scope")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address -fsanitize-address-use-after-scope")
|
||||
endif()
|
||||
|
||||
# NOTE: Running libzmq under TSAN doesn't make much sense -- synchronization in libzmq is to some extent
|
||||
# handled by the code "knowing" what threads are allowed to do, rather than by enforcing those
|
||||
# restrictions, so TSAN generates a lot of (presumably) false positives from libzmq.
|
||||
# The settings below are intended to enable libzmq to be built with minimal support for TSAN
|
||||
# such that it can be used along with other code that is also built with TSAN.
|
||||
option(ENABLE_TSAN "Build with thread sanitizer" OFF)
|
||||
if(ENABLE_TSAN)
|
||||
message(STATUS "Instrumenting with Thread Sanitizer")
|
||||
set(CMAKE_BUILD_TYPE "RelWithDebInfo")
|
||||
set(TSAN_FLAGS "-fno-omit-frame-pointer -fsanitize=thread")
|
||||
set(TSAN_CCFLAGS "${TSAN_CCFLAGS} -mllvm -tsan-instrument-memory-accesses=0")
|
||||
set(TSAN_CCFLAGS "${TSAN_CCFLAGS} -mllvm -tsan-instrument-atomics=0")
|
||||
set(TSAN_CCFLAGS "${TSAN_CCFLAGS} -mllvm -tsan-instrument-func-entry-exit=1")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${TSAN_FLAGS} ${TSAN_CCFLAGS} -fPIE")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${TSAN_FLAGS} ${TSAN_CCFLAGS} -fPIE")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${TSAN_FLAGS} -pie -Qunused-arguments")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${TSAN_FLAGS} -pie -Qunused-arguments")
|
||||
endif()
|
||||
|
||||
option(ENABLE_UBSAN "Build with undefined behavior sanitizer" OFF)
|
||||
if(ENABLE_UBSAN)
|
||||
message(STATUS "Instrumenting with Undefined Behavior Sanitizer")
|
||||
set(CMAKE_BUILD_TYPE "RelWithDebInfo")
|
||||
set(UBSAN_FLAGS "${UBSAN_FLAGS} -fno-omit-frame-pointer")
|
||||
set(UBSAN_FLAGS "${UBSAN_FLAGS} -fsanitize=undefined")
|
||||
set(UBSAN_FLAGS "${UBSAN_FLAGS} -fsanitize=implicit-conversion")
|
||||
set(UBSAN_FLAGS "${UBSAN_FLAGS} -fsanitize=implicit-integer-truncation")
|
||||
set(UBSAN_FLAGS "${UBSAN_FLAGS} -fsanitize=integer")
|
||||
set(UBSAN_FLAGS "${UBSAN_FLAGS} -fsanitize=nullability")
|
||||
set(UBSAN_FLAGS "${UBSAN_FLAGS} -fsanitize=vptr")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${UBSAN_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${UBSAN_FLAGS}")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${UBSAN_FLAGS}")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${UBSAN_FLAGS}")
|
||||
endif()
|
||||
|
||||
option(ENABLE_INTRINSICS "Build using compiler intrinsics for atomic ops" OFF)
|
||||
if(ENABLE_INTRINSICS)
|
||||
message(STATUS "Using compiler intrinsics for atomic ops")
|
||||
add_definitions(-DZMQ_HAVE_ATOMIC_INTRINSICS)
|
||||
endif()
|
||||
|
||||
set(ZMQ_OUTPUT_BASENAME
|
||||
"zmq"
|
||||
CACHE STRING "Output zmq library base name")
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} STREQUAL Darwin)
|
||||
# Find more information: https://cmake.org/Wiki/CMake_RPATH_handling
|
||||
|
||||
# Apply CMP0042: MACOSX_RPATH is enabled by default
|
||||
cmake_policy(SET CMP0042 NEW)
|
||||
|
||||
# Add an install rpath if it is not a system directory
|
||||
list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}" isSystemDir)
|
||||
if("${isSystemDir}" STREQUAL "-1")
|
||||
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}")
|
||||
endif()
|
||||
|
||||
# Add linker search paths pointing to external dependencies
|
||||
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||
endif()
|
||||
|
||||
if (NOT MSVC)
|
||||
if(NOT CMAKE_CXX_FLAGS MATCHES "-std=")
|
||||
# use C++11 by default if supported
|
||||
check_cxx_compiler_flag("-std=gnu++11" COMPILER_SUPPORTS_CXX11)
|
||||
if(COMPILER_SUPPORTS_CXX11)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
|
||||
endif()
|
||||
endif()
|
||||
if(NOT CMAKE_C_FLAGS MATCHES "-std=")
|
||||
check_c_compiler_flag("-std=gnu11" COMPILER_SUPPORTS_C11)
|
||||
if(COMPILER_SUPPORTS_C11)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu11")
|
||||
else()
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# clang 6 has a warning that does not make sense on multi-platform code
|
||||
check_cxx_compiler_flag("-Wno-tautological-constant-compare" CXX_HAS_TAUT_WARNING)
|
||||
if(CXX_HAS_TAUT_WARNING)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-tautological-constant-compare")
|
||||
endif()
|
||||
check_c_compiler_flag("-Wno-tautological-constant-compare" CC_HAS_TAUT_WARNING)
|
||||
if(CC_HAS_TAUT_WARNING)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-tautological-constant-compare")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Will be used to add flags to pkg-config useful when apps want to statically link
|
||||
set(pkg_config_libs_private "")
|
||||
set(pkg_config_names_private "")
|
||||
|
||||
option(WITH_OPENPGM "Build with support for OpenPGM" OFF)
|
||||
option(WITH_NORM "Build with support for NORM" OFF)
|
||||
option(WITH_VMCI "Build with support for VMware VMCI socket" OFF)
|
||||
|
||||
if(APPLE)
|
||||
option(ZMQ_BUILD_FRAMEWORK "Build as OS X framework" OFF)
|
||||
endif()
|
||||
|
||||
if(EXISTS "${CMAKE_SOURCE_DIR}/.git")
|
||||
message(STATUS "Build and install draft classes and methods")
|
||||
option(ENABLE_DRAFTS "Build and install draft classes and methods" ON)
|
||||
else()
|
||||
message(STATUS "Not building draft classes and methods")
|
||||
option(ENABLE_DRAFTS "Build and install draft classes and methods" OFF)
|
||||
endif()
|
||||
|
||||
# Enable WebSocket transport and RadixTree
|
||||
if(ENABLE_DRAFTS)
|
||||
set(ZMQ_BUILD_DRAFT_API 1)
|
||||
option(ENABLE_WS "Enable WebSocket transport" ON)
|
||||
option(ENABLE_RADIX_TREE "Use radix tree implementation to manage subscriptions" ON)
|
||||
else()
|
||||
option(ENABLE_WS "Enable WebSocket transport" OFF)
|
||||
option(ENABLE_RADIX_TREE "Use radix tree implementation to manage subscriptions" OFF)
|
||||
endif()
|
||||
|
||||
if(ENABLE_RADIX_TREE)
|
||||
message(STATUS "Using radix tree implementation to manage subscriptions")
|
||||
set(ZMQ_USE_RADIX_TREE 1)
|
||||
endif()
|
||||
|
||||
if(ENABLE_WS)
|
||||
list(
|
||||
APPEND
|
||||
sources
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/ws_address.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/ws_connecter.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/ws_decoder.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/ws_encoder.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/ws_engine.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/ws_listener.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/ws_address.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/ws_connecter.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/ws_decoder.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/ws_encoder.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/ws_engine.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/ws_listener.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/ws_protocol.hpp)
|
||||
set(ZMQ_HAVE_WS 1)
|
||||
|
||||
message(STATUS "Enable WebSocket transport")
|
||||
|
||||
option(WITH_TLS "Use TLS for WSS support" ON)
|
||||
option(WITH_NSS "Use NSS instead of builtin sha1" OFF)
|
||||
|
||||
if(WITH_TLS)
|
||||
find_package("GnuTLS" 3.6.7)
|
||||
if(GNUTLS_FOUND)
|
||||
set(pkg_config_names_private "${pkg_config_names_private} gnutls")
|
||||
list(APPEND sources ${CMAKE_CURRENT_SOURCE_DIR}/src/wss_address.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/wss_address.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/wss_engine.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/wss_engine.cpp)
|
||||
|
||||
message(STATUS "Enable WSS transport")
|
||||
set(ZMQ_USE_GNUTLS 1)
|
||||
set(ZMQ_HAVE_WSS 1)
|
||||
else()
|
||||
message(WARNING "No WSS support, you may want to install GnuTLS and run cmake again")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT ZMQ_USE_GNUTLS)
|
||||
if(WITH_NSS)
|
||||
pkg_check_modules(NSS3 "nss")
|
||||
if(NSS3_FOUND)
|
||||
set(pkg_config_names_private "${pkg_config_names_private} nss")
|
||||
message(STATUS "Using NSS")
|
||||
set(ZMQ_USE_NSS 1)
|
||||
else()
|
||||
find_package("NSS3")
|
||||
if(NSS3_FOUND)
|
||||
set(pkg_config_libs_private "${pkg_config_libs_private} -lnss3")
|
||||
message(STATUS "Using NSS")
|
||||
set(ZMQ_USE_NSS 1)
|
||||
else()
|
||||
message(WARNING "No nss installed, if you don't want builtin SHA1, install NSS or GnuTLS")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
if(NOT ZMQ_USE_NSS)
|
||||
list(APPEND sources ${CMAKE_CURRENT_SOURCE_DIR}/external/sha1/sha1.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/external/sha1/sha1.h)
|
||||
message(STATUS "Using builtin sha1")
|
||||
set(ZMQ_USE_BUILTIN_SHA1 1)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT MSVC)
|
||||
option(WITH_LIBBSD "Use libbsd instead of builtin strlcpy" ON)
|
||||
if(WITH_LIBBSD)
|
||||
pkg_check_modules(LIBBSD "libbsd")
|
||||
if(LIBBSD_FOUND)
|
||||
message(STATUS "Using libbsd")
|
||||
set(pkg_config_names_private "${pkg_config_names_private} libbsd")
|
||||
set(ZMQ_HAVE_LIBBSD 1)
|
||||
endif()
|
||||
endif()
|
||||
check_cxx_symbol_exists(strlcpy string.h ZMQ_HAVE_STRLCPY)
|
||||
endif()
|
||||
|
||||
# Select curve encryption library, defaults to tweetnacl To use libsodium instead, use --with-libsodium(must be
|
||||
# installed) To disable curve, use --disable-curve
|
||||
|
||||
option(WITH_LIBSODIUM "Use libsodium instead of built-in tweetnacl" ON)
|
||||
option(WITH_LIBSODIUM_STATIC "Use static libsodium library" OFF)
|
||||
option(ENABLE_CURVE "Enable CURVE security" ON)
|
||||
|
||||
if(ENABLE_CURVE)
|
||||
if(WITH_LIBSODIUM)
|
||||
if(sodium_FOUND)
|
||||
message(STATUS "Using libsodium for CURVE security")
|
||||
set(ZMQ_USE_LIBSODIUM 1)
|
||||
set(ZMQ_HAVE_CURVE 1)
|
||||
else()
|
||||
message(
|
||||
WARNING
|
||||
"libsodium not installed, instead using builtin tweetnacl, you may want to install libsodium and run cmake again"
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
if(NOT ZMQ_HAVE_CURVE)
|
||||
message(STATUS "Using tweetnacl for CURVE security")
|
||||
list(APPEND sources ${CMAKE_CURRENT_SOURCE_DIR}/src/tweetnacl.c)
|
||||
set(ZMQ_USE_TWEETNACL 1)
|
||||
set(ZMQ_HAVE_CURVE 1)
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "CURVE security is disabled")
|
||||
endif()
|
||||
|
||||
set(SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
|
||||
option(WITH_MILITANT "Enable militant assertions" OFF)
|
||||
if(WITH_MILITANT)
|
||||
add_definitions(-DZMQ_ACT_MILITANT)
|
||||
endif()
|
||||
|
||||
set(API_POLLER
|
||||
""
|
||||
CACHE STRING "Choose polling system for zmq_poll(er)_*. valid values are
|
||||
poll or select [default=poll unless POLLER=select]")
|
||||
|
||||
set(POLLER
|
||||
""
|
||||
CACHE STRING "Choose polling system for I/O threads. valid values are
|
||||
kqueue, epoll, devpoll, pollset, poll or select [default=autodetect]")
|
||||
|
||||
if(WIN32)
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "WindowsStore" AND CMAKE_SYSTEM_VERSION MATCHES "^10.0")
|
||||
set(ZMQ_HAVE_WINDOWS_UWP ON)
|
||||
set(ZMQ_HAVE_IPC OFF)
|
||||
# to remove compile warninging "D9002 ignoring unknown option"
|
||||
string(REPLACE "/Zi" "" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG})
|
||||
set(CMAKE_CXX_FLAGS_DEBUG
|
||||
${CMAKE_CXX_FLAGS_DEBUG}
|
||||
CACHE STRING "" FORCE)
|
||||
string(REPLACE "/Zi" "" CMAKE_CXX_FLAGS_RELWITHDEBINFO ${CMAKE_CXX_FLAGS_RELWITHDEBINFO})
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO
|
||||
${CMAKE_CXX_FLAGS_RELWITHDEBINFO}
|
||||
CACHE STRING "" FORCE)
|
||||
string(REPLACE "/Zi" "" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG})
|
||||
endif()
|
||||
# from https://stackoverflow.com/a/40217291/2019765
|
||||
macro(get_WIN32_WINNT version)
|
||||
if(CMAKE_SYSTEM_VERSION)
|
||||
set(ver ${CMAKE_SYSTEM_VERSION})
|
||||
string(REGEX MATCH "^([0-9]+).([0-9])" ver ${ver})
|
||||
string(REGEX MATCH "^([0-9]+)" verMajor ${ver})
|
||||
# Check for Windows 10, b/c we'll need to convert to hex 'A'.
|
||||
if("${verMajor}" MATCHES "10")
|
||||
set(verMajor "A")
|
||||
string(REGEX REPLACE "^([0-9]+)" ${verMajor} ver ${ver})
|
||||
endif("${verMajor}" MATCHES "10")
|
||||
# Remove all remaining '.' characters.
|
||||
string(REPLACE "." "" ver ${ver})
|
||||
# Prepend each digit with a zero.
|
||||
string(REGEX REPLACE "([0-9A-Z])" "0\\1" ver ${ver})
|
||||
set(${version} "0x${ver}")
|
||||
endif(CMAKE_SYSTEM_VERSION)
|
||||
endmacro(get_WIN32_WINNT)
|
||||
|
||||
get_win32_winnt(ZMQ_WIN32_WINNT_DEFAULT)
|
||||
message(STATUS "Detected _WIN32_WINNT from CMAKE_SYSTEM_VERSION: ${ZMQ_WIN32_WINNT_DEFAULT}")
|
||||
|
||||
# TODO limit _WIN32_WINNT to the actual Windows SDK version, which might be different from the default version
|
||||
# installed with Visual Studio
|
||||
if(MSVC_VERSION STREQUAL "1500" AND CMAKE_SYSTEM_VERSION VERSION_GREATER "6.0")
|
||||
set(ZMQ_WIN32_WINNT_LIMIT "0x0600")
|
||||
elseif(MSVC_VERSION STREQUAL "1600" AND CMAKE_SYSTEM_VERSION VERSION_GREATER "6.1")
|
||||
set(ZMQ_WIN32_WINNT_LIMIT "0x0601")
|
||||
elseif(MSVC_VERSION STREQUAL "1700" AND CMAKE_SYSTEM_VERSION VERSION_GREATER "6.1")
|
||||
set(ZMQ_WIN32_WINNT_LIMIT "0x0601")
|
||||
elseif(MSVC_VERSION STREQUAL "1800" AND CMAKE_SYSTEM_VERSION VERSION_GREATER "6.2")
|
||||
set(ZMQ_WIN32_WINNT_LIMIT "0x0602")
|
||||
endif()
|
||||
if(ZMQ_WIN32_WINNT_LIMIT)
|
||||
message(
|
||||
STATUS
|
||||
"Mismatch of Visual Studio Version (${MSVC_VERSION}) and CMAKE_SYSTEM_VERSION (${CMAKE_SYSTEM_VERSION}), limiting _WIN32_WINNT to ${ZMQ_WIN32_WINNT_LIMIT}, you may override this by setting ZMQ_WIN32_WINNT"
|
||||
)
|
||||
set(ZMQ_WIN32_WINNT_DEFAULT "${ZMQ_WIN32_WINNT_LIMIT}")
|
||||
endif()
|
||||
|
||||
set(ZMQ_WIN32_WINNT
|
||||
"${ZMQ_WIN32_WINNT_DEFAULT}"
|
||||
CACHE STRING "Value to set _WIN32_WINNT to for building [default=autodetect from build environment]")
|
||||
|
||||
# On Windows Vista or greater, with MSVC 2013 or greater, default to epoll (which is required on Win 10 for ipc
|
||||
# support)
|
||||
if(ZMQ_WIN32_WINNT GREATER "0x05FF"
|
||||
AND MSVC_VERSION GREATER 1799
|
||||
AND POLLER STREQUAL ""
|
||||
AND NOT ZMQ_HAVE_WINDOWS_UWP)
|
||||
set(POLLER "epoll")
|
||||
endif()
|
||||
|
||||
add_definitions(-D_WIN32_WINNT=${ZMQ_WIN32_WINNT})
|
||||
endif(WIN32)
|
||||
|
||||
if(NOT MSVC)
|
||||
if(POLLER STREQUAL "")
|
||||
check_cxx_symbol_exists(kqueue sys/event.h HAVE_KQUEUE)
|
||||
if(HAVE_KQUEUE)
|
||||
set(POLLER "kqueue")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(POLLER STREQUAL "")
|
||||
check_cxx_symbol_exists(epoll_create sys/epoll.h HAVE_EPOLL)
|
||||
if(HAVE_EPOLL)
|
||||
set(POLLER "epoll")
|
||||
check_cxx_symbol_exists(epoll_create1 sys/epoll.h HAVE_EPOLL_CLOEXEC)
|
||||
if(HAVE_EPOLL_CLOEXEC)
|
||||
set(ZMQ_IOTHREAD_POLLER_USE_EPOLL_CLOEXEC 1)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(POLLER STREQUAL "")
|
||||
set(CMAKE_EXTRA_INCLUDE_FILES sys/devpoll.h)
|
||||
check_type_size("struct pollfd" DEVPOLL)
|
||||
set(CMAKE_EXTRA_INCLUDE_FILES)
|
||||
if(HAVE_DEVPOLL)
|
||||
set(POLLER "devpoll")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(POLLER STREQUAL "")
|
||||
check_cxx_symbol_exists(pollset_create sys/pollset.h HAVE_POLLSET)
|
||||
if(HAVE_POLLSET)
|
||||
set(POLLER "pollset")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(POLLER STREQUAL "")
|
||||
check_cxx_symbol_exists(poll poll.h HAVE_POLL)
|
||||
if(HAVE_POLL)
|
||||
set(POLLER "poll")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(POLLER STREQUAL "")
|
||||
if(WIN32)
|
||||
set(HAVE_SELECT 1)
|
||||
else()
|
||||
check_cxx_symbol_exists(select sys/select.h HAVE_SELECT)
|
||||
endif()
|
||||
if(HAVE_SELECT)
|
||||
set(POLLER "select")
|
||||
else()
|
||||
message(FATAL_ERROR "Could not autodetect polling method")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(POLLER STREQUAL "kqueue"
|
||||
OR POLLER STREQUAL "epoll"
|
||||
OR POLLER STREQUAL "devpoll"
|
||||
OR POLLER STREQUAL "pollset"
|
||||
OR POLLER STREQUAL "poll"
|
||||
OR POLLER STREQUAL "select")
|
||||
message(STATUS "Using polling method in I/O threads: ${POLLER}")
|
||||
string(TOUPPER ${POLLER} UPPER_POLLER)
|
||||
set(ZMQ_IOTHREAD_POLLER_USE_${UPPER_POLLER} 1)
|
||||
else()
|
||||
message(FATAL_ERROR "Invalid polling method")
|
||||
endif()
|
||||
|
||||
if(POLLER STREQUAL "epoll" AND WIN32)
|
||||
message(STATUS "Including wepoll")
|
||||
list(APPEND sources ${CMAKE_CURRENT_SOURCE_DIR}/external/wepoll/wepoll.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/external/wepoll/wepoll.h)
|
||||
endif()
|
||||
|
||||
if(API_POLLER STREQUAL "")
|
||||
if(POLLER STREQUAL "select")
|
||||
set(API_POLLER "select")
|
||||
else()
|
||||
set(API_POLLER "poll")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
message(STATUS "Using polling method in zmq_poll(er)_* API: ${API_POLLER}")
|
||||
string(TOUPPER ${API_POLLER} UPPER_API_POLLER)
|
||||
set(ZMQ_POLL_BASED_ON_${UPPER_API_POLLER} 1)
|
||||
|
||||
execute_process(
|
||||
COMMAND getconf LEVEL1_DCACHE_LINESIZE
|
||||
OUTPUT_VARIABLE CACHELINE_SIZE
|
||||
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
if(CACHELINE_SIZE STREQUAL ""
|
||||
OR CACHELINE_SIZE EQUAL 0
|
||||
OR CACHELINE_SIZE EQUAL -1)
|
||||
set(ZMQ_CACHELINE_SIZE 64)
|
||||
else()
|
||||
set(ZMQ_CACHELINE_SIZE ${CACHELINE_SIZE})
|
||||
endif()
|
||||
message(STATUS "Using ${ZMQ_CACHELINE_SIZE} bytes alignment for lock-free data structures")
|
||||
|
||||
if(NOT CYGWIN)
|
||||
# TODO cannot we simply do 'if(WIN32) set(ZMQ_HAVE_WINDOWS ON)' or similar?
|
||||
check_include_files(windows.h ZMQ_HAVE_WINDOWS)
|
||||
endif()
|
||||
|
||||
if(NOT WIN32)
|
||||
set(ZMQ_HAVE_IPC 1)
|
||||
else()
|
||||
check_include_files("winsock2.h;afunix.h" ZMQ_HAVE_IPC)
|
||||
endif()
|
||||
|
||||
# ##################### BEGIN condition_variable_t selection
|
||||
if(NOT ZMQ_CV_IMPL)
|
||||
# prefer C++11 STL std::condition_variable implementation, if available
|
||||
check_include_files(condition_variable ZMQ_HAVE_STL_CONDITION_VARIABLE LANGUAGE CXX)
|
||||
|
||||
if(ZMQ_HAVE_STL_CONDITION_VARIABLE)
|
||||
set(ZMQ_CV_IMPL_DEFAULT "stl11")
|
||||
else()
|
||||
if(WIN32 AND NOT CMAKE_SYSTEM_VERSION VERSION_LESS "6.0")
|
||||
# Win32API CONDITION_VARIABLE is supported from Windows Vista only
|
||||
set(ZMQ_CV_IMPL_DEFAULT "win32api")
|
||||
elseif(CMAKE_USE_PTHREADS_INIT)
|
||||
set(ZMQ_CV_IMPL_DEFAULT "pthreads")
|
||||
else()
|
||||
set(ZMQ_CV_IMPL_DEFAULT "none")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# TODO a vxworks implementation also exists, but vxworks is not currently supported with cmake at all
|
||||
set(ZMQ_CV_IMPL
|
||||
"${ZMQ_CV_IMPL_DEFAULT}"
|
||||
CACHE STRING "Choose condition_variable_t implementation. Valid values are
|
||||
stl11, win32api, pthreads, none [default=autodetect]")
|
||||
endif()
|
||||
|
||||
message(STATUS "Using condition_variable_t implementation: ${ZMQ_CV_IMPL}")
|
||||
if(ZMQ_CV_IMPL STREQUAL "stl11")
|
||||
set(ZMQ_USE_CV_IMPL_STL11 1)
|
||||
elseif(ZMQ_CV_IMPL STREQUAL "win32api")
|
||||
set(ZMQ_USE_CV_IMPL_WIN32API 1)
|
||||
elseif(ZMQ_CV_IMPL STREQUAL "pthreads")
|
||||
set(ZMQ_USE_CV_IMPL_PTHREADS 1)
|
||||
elseif(ZMQ_CV_IMPL STREQUAL "none")
|
||||
set(ZMQ_USE_CV_IMPL_NONE 1)
|
||||
else()
|
||||
message(ERROR "Unknown value for ZMQ_CV_IMPL: ${ZMQ_CV_IMPL}")
|
||||
endif()
|
||||
# ##################### END condition_variable_t selection
|
||||
|
||||
if(NOT MSVC)
|
||||
check_include_files(ifaddrs.h ZMQ_HAVE_IFADDRS)
|
||||
check_include_files(sys/uio.h ZMQ_HAVE_UIO)
|
||||
check_include_files(sys/eventfd.h ZMQ_HAVE_EVENTFD)
|
||||
if(ZMQ_HAVE_EVENTFD AND NOT CMAKE_CROSSCOMPILING)
|
||||
zmq_check_efd_cloexec()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ZMQ_HAVE_WINDOWS)
|
||||
# Cannot use check_library_exists because the symbol is always declared as char(*)(void)
|
||||
set(CMAKE_REQUIRED_LIBRARIES "ws2_32.lib")
|
||||
check_cxx_symbol_exists(WSAStartup "winsock2.h" HAVE_WS2_32)
|
||||
|
||||
set(CMAKE_REQUIRED_LIBRARIES "rpcrt4.lib")
|
||||
check_cxx_symbol_exists(UuidCreateSequential "rpc.h" HAVE_RPCRT4)
|
||||
|
||||
set(CMAKE_REQUIRED_LIBRARIES "iphlpapi.lib")
|
||||
check_cxx_symbol_exists(GetAdaptersAddresses "winsock2.h;iphlpapi.h" HAVE_IPHLAPI)
|
||||
check_cxx_symbol_exists(if_nametoindex "iphlpapi.h" HAVE_IF_NAMETOINDEX)
|
||||
|
||||
set(CMAKE_REQUIRED_LIBRARIES "")
|
||||
# TODO: This not the symbol we're looking for. What is the symbol?
|
||||
check_library_exists(ws2 fopen "" HAVE_WS2)
|
||||
else()
|
||||
check_cxx_symbol_exists(if_nametoindex net/if.h HAVE_IF_NAMETOINDEX)
|
||||
check_cxx_symbol_exists(SO_PEERCRED sys/socket.h ZMQ_HAVE_SO_PEERCRED)
|
||||
check_cxx_symbol_exists(LOCAL_PEERCRED sys/socket.h ZMQ_HAVE_LOCAL_PEERCRED)
|
||||
endif()
|
||||
|
||||
if(NOT MINGW)
|
||||
find_library(RT_LIBRARY rt)
|
||||
if(RT_LIBRARY)
|
||||
set(pkg_config_libs_private "${pkg_config_libs_private} -lrt")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
find_package(Threads)
|
||||
|
||||
if(WIN32 AND NOT CYGWIN)
|
||||
if(NOT HAVE_WS2_32 AND NOT HAVE_WS2)
|
||||
message(FATAL_ERROR "Cannot link to ws2_32 or ws2")
|
||||
endif()
|
||||
|
||||
if(NOT HAVE_RPCRT4)
|
||||
message(FATAL_ERROR "Cannot link to rpcrt4")
|
||||
endif()
|
||||
|
||||
if(NOT HAVE_IPHLAPI)
|
||||
message(FATAL_ERROR "Cannot link to iphlapi")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT MSVC)
|
||||
set(CMAKE_REQUIRED_LIBRARIES rt)
|
||||
check_cxx_symbol_exists(clock_gettime time.h HAVE_CLOCK_GETTIME)
|
||||
set(CMAKE_REQUIRED_LIBRARIES)
|
||||
|
||||
check_cxx_symbol_exists(fork unistd.h HAVE_FORK)
|
||||
check_cxx_symbol_exists(gethrtime sys/time.h HAVE_GETHRTIME)
|
||||
check_cxx_symbol_exists(mkdtemp stdlib.h HAVE_MKDTEMP)
|
||||
check_cxx_symbol_exists(accept4 sys/socket.h HAVE_ACCEPT4)
|
||||
check_cxx_symbol_exists(strnlen string.h HAVE_STRNLEN)
|
||||
else()
|
||||
set(HAVE_STRNLEN 1)
|
||||
endif()
|
||||
|
||||
add_definitions(-D_REENTRANT -D_THREAD_SAFE)
|
||||
add_definitions(-DZMQ_CUSTOM_PLATFORM_HPP)
|
||||
|
||||
option(ENABLE_EVENTFD "Enable/disable eventfd" ZMQ_HAVE_EVENTFD)
|
||||
|
||||
macro(zmq_check_cxx_flag_prepend flag)
|
||||
check_cxx_compiler_flag("${flag}" HAVE_FLAG_${flag})
|
||||
|
||||
if(HAVE_FLAG_${flag})
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
option(ENABLE_ANALYSIS "Build with static analysis(make take very long)" OFF)
|
||||
|
||||
if(MSVC)
|
||||
if(ENABLE_ANALYSIS)
|
||||
zmq_check_cxx_flag_prepend("/W4")
|
||||
|
||||
zmq_check_cxx_flag_prepend("/analyze")
|
||||
|
||||
# C++11/14/17-specific, but maybe possible via conditional defines
|
||||
zmq_check_cxx_flag_prepend("/wd26440") # Function '...' can be declared 'noexcept'
|
||||
zmq_check_cxx_flag_prepend("/wd26432") # If you define or delete any default operation in the type '...', define or
|
||||
# delete them all
|
||||
zmq_check_cxx_flag_prepend("/wd26439") # This kind of function may not throw. Declare it 'noexcept'
|
||||
zmq_check_cxx_flag_prepend("/wd26447") # The function is declared 'noexcept' but calls function '...' which may
|
||||
# throw exceptions
|
||||
zmq_check_cxx_flag_prepend("/wd26433") # Function '...' should be marked with 'override'
|
||||
zmq_check_cxx_flag_prepend("/wd26409") # Avoid calling new and delete explicitly, use std::make_unique<T> instead
|
||||
# Requires GSL
|
||||
zmq_check_cxx_flag_prepend("/wd26429") # Symbol '...' is never tested for nullness, it can be marked as not_null
|
||||
zmq_check_cxx_flag_prepend("/wd26446") # Prefer to use gsl::at()
|
||||
zmq_check_cxx_flag_prepend("/wd26481") # Don't use pointer arithmetic. Use span instead
|
||||
zmq_check_cxx_flag_prepend("/wd26472") # Don't use a static_cast for arithmetic conversions. Use brace
|
||||
# initialization, gsl::narrow_cast or gsl::narow
|
||||
zmq_check_cxx_flag_prepend("/wd26448") # Consider using gsl::finally if final action is intended
|
||||
zmq_check_cxx_flag_prepend("/wd26400") # Do not assign the result of an allocation or a function call with an
|
||||
# owner<T> return value to a raw pointer, use owner<T> instead
|
||||
zmq_check_cxx_flag_prepend("/wd26485") # Expression '...': No array to pointer decay(bounds.3)
|
||||
else()
|
||||
zmq_check_cxx_flag_prepend("/W3")
|
||||
endif()
|
||||
|
||||
if(MSVC_IDE)
|
||||
set(MSVC_TOOLSET "-${CMAKE_VS_PLATFORM_TOOLSET}")
|
||||
else()
|
||||
set(MSVC_TOOLSET "")
|
||||
endif()
|
||||
else()
|
||||
zmq_check_cxx_flag_prepend("-Wall")
|
||||
endif()
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
zmq_check_cxx_flag_prepend("-Wextra")
|
||||
endif()
|
||||
|
||||
option(LIBZMQ_PEDANTIC "" ON)
|
||||
option(LIBZMQ_WERROR "" OFF)
|
||||
|
||||
# TODO: why is -Wno-long-long defined differently than in configure.ac?
|
||||
if(NOT MSVC)
|
||||
zmq_check_cxx_flag_prepend("-Wno-long-long")
|
||||
zmq_check_cxx_flag_prepend("-Wno-uninitialized")
|
||||
|
||||
if(LIBZMQ_PEDANTIC)
|
||||
zmq_check_cxx_flag_prepend("-pedantic")
|
||||
|
||||
if(${CMAKE_CXX_COMPILER_ID} MATCHES "Intel")
|
||||
zmq_check_cxx_flag_prepend("-strict-ansi")
|
||||
endif()
|
||||
|
||||
if(${CMAKE_CXX_COMPILER_ID} MATCHES "SunPro")
|
||||
zmq_check_cxx_flag_prepend("-compat=5")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(LIBZMQ_WERROR)
|
||||
if(MSVC)
|
||||
zmq_check_cxx_flag_prepend("/WX")
|
||||
else()
|
||||
zmq_check_cxx_flag_prepend("-Werror")
|
||||
if(NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||
zmq_check_cxx_flag_prepend("-errwarn=%all")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^sparc")
|
||||
zmq_check_cxx_flag_prepend("-mcpu=v9")
|
||||
endif()
|
||||
|
||||
if(${CMAKE_CXX_COMPILER_ID} MATCHES "SunPro")
|
||||
zmq_check_cxx_flag_prepend("-features=zla")
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "SunOS"
|
||||
OR CMAKE_SYSTEM_NAME MATCHES "NetBSD"
|
||||
OR CMAKE_SYSTEM_NAME MATCHES "QNX")
|
||||
message(STATUS "Checking whether atomic operations can be used")
|
||||
check_c_source_compiles(
|
||||
"\
|
||||
#include <atomic.h> \
|
||||
\
|
||||
int main() \
|
||||
{ \
|
||||
uint32_t value; \
|
||||
atomic_cas_32(&value, 0, 0); \
|
||||
return 0; \
|
||||
} \
|
||||
"
|
||||
HAVE_ATOMIC_H)
|
||||
|
||||
if(NOT HAVE_ATOMIC_H)
|
||||
set(ZMQ_FORCE_MUTEXES 1)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT ANDROID)
|
||||
zmq_check_noexcept()
|
||||
endif()
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
if(NOT CMAKE_CROSSCOMPILING AND NOT MSVC)
|
||||
zmq_check_sock_cloexec()
|
||||
zmq_check_o_cloexec()
|
||||
zmq_check_so_bindtodevice()
|
||||
zmq_check_so_keepalive()
|
||||
zmq_check_so_priority()
|
||||
zmq_check_tcp_keepcnt()
|
||||
zmq_check_tcp_keepidle()
|
||||
zmq_check_tcp_keepintvl()
|
||||
zmq_check_tcp_keepalive()
|
||||
zmq_check_tcp_tipc()
|
||||
zmq_check_pthread_setname()
|
||||
zmq_check_pthread_setaffinity()
|
||||
zmq_check_getrandom()
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "Linux"
|
||||
OR CMAKE_SYSTEM_NAME MATCHES "GNU/kFreeBSD"
|
||||
OR CMAKE_SYSTEM_NAME MATCHES "GNU/Hurd"
|
||||
OR CYGWIN)
|
||||
add_definitions(-D_GNU_SOURCE)
|
||||
elseif(CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
|
||||
add_definitions(-D__BSD_VISIBLE)
|
||||
elseif(CMAKE_SYSTEM_NAME MATCHES "NetBSD")
|
||||
add_definitions(-D_NETBSD_SOURCE)
|
||||
elseif(CMAKE_SYSTEM_NAME MATCHES "OpenBSD")
|
||||
add_definitions(-D_OPENBSD_SOURCE)
|
||||
elseif(CMAKE_SYSTEM_NAME MATCHES "SunOS")
|
||||
add_definitions(-D_PTHREADS)
|
||||
elseif(CMAKE_SYSTEM_NAME MATCHES "HP-UX")
|
||||
add_definitions(-D_POSIX_C_SOURCE=200112L)
|
||||
zmq_check_cxx_flag_prepend(-Ae)
|
||||
elseif(CMAKE_SYSTEM_NAME MATCHES "Darwin")
|
||||
add_definitions(-D_DARWIN_C_SOURCE)
|
||||
endif()
|
||||
|
||||
find_package(AsciiDoc)
|
||||
|
||||
cmake_dependent_option(WITH_DOC "Build Reference Guide documentation(requires DocBook)" ON "ASCIIDOC_FOUND;NOT WIN32"
|
||||
OFF) # Do not build docs on Windows due to issues with symlinks
|
||||
|
||||
if(MSVC)
|
||||
if(WITH_OPENPGM)
|
||||
# set(OPENPGM_ROOT "" CACHE PATH "Location of OpenPGM")
|
||||
set(OPENPGM_VERSION_MAJOR 5)
|
||||
set(OPENPGM_VERSION_MINOR 2)
|
||||
set(OPENPGM_VERSION_MICRO 122)
|
||||
if(CMAKE_CL_64)
|
||||
find_path(
|
||||
OPENPGM_ROOT include/pgm/pgm.h
|
||||
PATHS
|
||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Miru\\OpenPGM ${OPENPGM_VERSION_MAJOR}.${OPENPGM_VERSION_MINOR}.${OPENPGM_VERSION_MICRO}]"
|
||||
NO_DEFAULT_PATH)
|
||||
message(STATUS "OpenPGM x64 detected - ${OPENPGM_ROOT}")
|
||||
else()
|
||||
find_path(
|
||||
OPENPGM_ROOT include/pgm/pgm.h
|
||||
PATHS
|
||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Miru\\OpenPGM ${OPENPGM_VERSION_MAJOR}.${OPENPGM_VERSION_MINOR}.${OPENPGM_VERSION_MICRO}]"
|
||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Miru\\OpenPGM ${OPENPGM_VERSION_MAJOR}.${OPENPGM_VERSION_MINOR}.${OPENPGM_VERSION_MICRO}]"
|
||||
NO_DEFAULT_PATH)
|
||||
message(STATUS "OpenPGM x86 detected - ${OPENPGM_ROOT}")
|
||||
endif()
|
||||
set(OPENPGM_INCLUDE_DIRS ${OPENPGM_ROOT}/include)
|
||||
set(OPENPGM_LIBRARY_DIRS ${OPENPGM_ROOT}/lib)
|
||||
set(OPENPGM_LIBRARIES
|
||||
optimized
|
||||
libpgm${MSVC_TOOLSET}-mt-${OPENPGM_VERSION_MAJOR}_${OPENPGM_VERSION_MINOR}_${OPENPGM_VERSION_MICRO}.lib debug
|
||||
libpgm${MSVC_TOOLSET}-mt-gd-${OPENPGM_VERSION_MAJOR}_${OPENPGM_VERSION_MINOR}_${OPENPGM_VERSION_MICRO}.lib)
|
||||
endif()
|
||||
else()
|
||||
if(WITH_OPENPGM)
|
||||
# message(FATAL_ERROR "WITH_OPENPGM not implemented")
|
||||
|
||||
if(NOT OPENPGM_PKGCONFIG_NAME)
|
||||
set(OPENPGM_PKGCONFIG_NAME "openpgm-5.2")
|
||||
endif()
|
||||
|
||||
set(OPENPGM_PKGCONFIG_NAME
|
||||
${OPENPGM_PKGCONFIG_NAME}
|
||||
CACHE STRING "Name pkg-config shall use to find openpgm libraries and include paths" FORCE)
|
||||
|
||||
pkg_check_modules(OPENPGM ${OPENPGM_PKGCONFIG_NAME})
|
||||
|
||||
if(OPENPGM_FOUND)
|
||||
message(STATUS ${OPENPGM_PKGCONFIG_NAME}" found")
|
||||
set(pkg_config_names_private "${pkg_config_names_private} ${OPENPGM_PKGCONFIG_NAME}")
|
||||
else()
|
||||
message(
|
||||
FATAL_ERROR
|
||||
${OPENPGM_PKGCONFIG_NAME}" not found. openpgm is searchd via `pkg-config ${OPENPGM_PKGCONFIG_NAME}`. Consider providing a valid OPENPGM_PKGCONFIG_NAME"
|
||||
)
|
||||
endif()
|
||||
|
||||
# DSO symbol visibility for openpgm
|
||||
if(HAVE_FLAG_VISIBILITY_HIDDEN)
|
||||
|
||||
elseif(HAVE_FLAG_LDSCOPE_HIDDEN)
|
||||
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# force off-tree build
|
||||
|
||||
if(${CMAKE_CURRENT_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_BINARY_DIR})
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"CMake generation is not allowed within the source directory! \
|
||||
Remove the CMakeCache.txt file and try again from another folder, e.g.: \
|
||||
\
|
||||
rm CMakeCache.txt \
|
||||
mkdir cmake-make \
|
||||
cd cmake-make \
|
||||
cmake ..")
|
||||
endif()
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# default to Release build
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||
# CMAKE_BUILD_TYPE is not used for multi-configuration generators like Visual Studio/XCode which instead use
|
||||
# CMAKE_CONFIGURATION_TYPES
|
||||
set(CMAKE_BUILD_TYPE
|
||||
Release
|
||||
CACHE STRING "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." FORCE)
|
||||
endif()
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# output directories
|
||||
|
||||
zmq_set_with_default(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${ZeroMQ_BINARY_DIR}/bin")
|
||||
if(UNIX)
|
||||
set(zmq_library_directory "lib")
|
||||
else()
|
||||
set(zmq_library_directory "bin")
|
||||
endif()
|
||||
zmq_set_with_default(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${ZeroMQ_BINARY_DIR}/${zmq_library_directory}")
|
||||
zmq_set_with_default(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${ZeroMQ_BINARY_DIR}/lib")
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# platform specifics
|
||||
|
||||
if(WIN32)
|
||||
# Socket limit is 16K(can be raised arbitrarily)
|
||||
add_definitions(-DFD_SETSIZE=16384)
|
||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||
add_definitions(-D_WINSOCK_DEPRECATED_NO_WARNINGS)
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
# Parallel make.
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MP")
|
||||
|
||||
# Compile the static lib with debug information included note: we assume here that the default flags contain some /Z
|
||||
# flag
|
||||
string(REGEX REPLACE "/Z.[^:]" "/Z7 " CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
|
||||
string(REGEX REPLACE "/Z.[^:]" "/Z7 " CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
|
||||
|
||||
# Optimization flags. http://msdn.microsoft.com/en-us/magazine/cc301698.aspx
|
||||
if(NOT ${CMAKE_BUILD_TYPE} MATCHES "Debug")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /GL")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /LTCG")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /LTCG")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /LTCG")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# source files
|
||||
|
||||
set(cxx-sources
|
||||
precompiled.cpp
|
||||
address.cpp
|
||||
channel.cpp
|
||||
client.cpp
|
||||
clock.cpp
|
||||
ctx.cpp
|
||||
curve_mechanism_base.cpp
|
||||
curve_client.cpp
|
||||
curve_server.cpp
|
||||
dealer.cpp
|
||||
devpoll.cpp
|
||||
dgram.cpp
|
||||
dist.cpp
|
||||
endpoint.cpp
|
||||
epoll.cpp
|
||||
err.cpp
|
||||
fq.cpp
|
||||
io_object.cpp
|
||||
io_thread.cpp
|
||||
ip.cpp
|
||||
ipc_address.cpp
|
||||
ipc_connecter.cpp
|
||||
ipc_listener.cpp
|
||||
kqueue.cpp
|
||||
lb.cpp
|
||||
mailbox.cpp
|
||||
mailbox_safe.cpp
|
||||
mechanism.cpp
|
||||
mechanism_base.cpp
|
||||
metadata.cpp
|
||||
msg.cpp
|
||||
mtrie.cpp
|
||||
norm_engine.cpp
|
||||
object.cpp
|
||||
options.cpp
|
||||
own.cpp
|
||||
null_mechanism.cpp
|
||||
pair.cpp
|
||||
peer.cpp
|
||||
pgm_receiver.cpp
|
||||
pgm_sender.cpp
|
||||
pgm_socket.cpp
|
||||
pipe.cpp
|
||||
plain_client.cpp
|
||||
plain_server.cpp
|
||||
poll.cpp
|
||||
poller_base.cpp
|
||||
polling_util.cpp
|
||||
pollset.cpp
|
||||
proxy.cpp
|
||||
pub.cpp
|
||||
pull.cpp
|
||||
push.cpp
|
||||
random.cpp
|
||||
raw_encoder.cpp
|
||||
raw_decoder.cpp
|
||||
raw_engine.cpp
|
||||
reaper.cpp
|
||||
rep.cpp
|
||||
req.cpp
|
||||
router.cpp
|
||||
select.cpp
|
||||
server.cpp
|
||||
session_base.cpp
|
||||
signaler.cpp
|
||||
socket_base.cpp
|
||||
socks.cpp
|
||||
socks_connecter.cpp
|
||||
stream.cpp
|
||||
stream_engine_base.cpp
|
||||
sub.cpp
|
||||
tcp.cpp
|
||||
tcp_address.cpp
|
||||
tcp_connecter.cpp
|
||||
tcp_listener.cpp
|
||||
thread.cpp
|
||||
trie.cpp
|
||||
radix_tree.cpp
|
||||
v1_decoder.cpp
|
||||
v1_encoder.cpp
|
||||
v2_decoder.cpp
|
||||
v2_encoder.cpp
|
||||
v3_1_encoder.cpp
|
||||
xpub.cpp
|
||||
xsub.cpp
|
||||
zmq.cpp
|
||||
zmq_utils.cpp
|
||||
decoder_allocators.cpp
|
||||
socket_poller.cpp
|
||||
timers.cpp
|
||||
config.hpp
|
||||
radio.cpp
|
||||
dish.cpp
|
||||
udp_engine.cpp
|
||||
udp_address.cpp
|
||||
scatter.cpp
|
||||
gather.cpp
|
||||
ip_resolver.cpp
|
||||
zap_client.cpp
|
||||
zmtp_engine.cpp
|
||||
# at least for VS, the header files must also be listed
|
||||
address.hpp
|
||||
array.hpp
|
||||
atomic_counter.hpp
|
||||
atomic_ptr.hpp
|
||||
blob.hpp
|
||||
channel.hpp
|
||||
client.hpp
|
||||
clock.hpp
|
||||
command.hpp
|
||||
compat.hpp
|
||||
condition_variable.hpp
|
||||
config.hpp
|
||||
ctx.hpp
|
||||
curve_client.hpp
|
||||
curve_client_tools.hpp
|
||||
curve_mechanism_base.hpp
|
||||
curve_server.hpp
|
||||
dbuffer.hpp
|
||||
dealer.hpp
|
||||
decoder.hpp
|
||||
decoder_allocators.hpp
|
||||
devpoll.hpp
|
||||
dgram.hpp
|
||||
dish.hpp
|
||||
dist.hpp
|
||||
encoder.hpp
|
||||
endpoint.hpp
|
||||
epoll.hpp
|
||||
err.hpp
|
||||
fd.hpp
|
||||
fq.hpp
|
||||
gather.hpp
|
||||
generic_mtrie.hpp
|
||||
generic_mtrie_impl.hpp
|
||||
gssapi_client.hpp
|
||||
gssapi_mechanism_base.hpp
|
||||
gssapi_server.hpp
|
||||
i_decoder.hpp
|
||||
i_encoder.hpp
|
||||
i_engine.hpp
|
||||
i_mailbox.hpp
|
||||
i_poll_events.hpp
|
||||
io_object.hpp
|
||||
io_thread.hpp
|
||||
ip.hpp
|
||||
ipc_address.hpp
|
||||
ipc_connecter.hpp
|
||||
ipc_listener.hpp
|
||||
kqueue.hpp
|
||||
lb.hpp
|
||||
likely.hpp
|
||||
macros.hpp
|
||||
mailbox.hpp
|
||||
mailbox_safe.hpp
|
||||
mechanism.hpp
|
||||
mechanism_base.hpp
|
||||
metadata.hpp
|
||||
msg.hpp
|
||||
mtrie.hpp
|
||||
mutex.hpp
|
||||
norm_engine.hpp
|
||||
null_mechanism.hpp
|
||||
object.hpp
|
||||
options.hpp
|
||||
own.hpp
|
||||
pair.hpp
|
||||
peer.hpp
|
||||
pgm_receiver.hpp
|
||||
pgm_sender.hpp
|
||||
pgm_socket.hpp
|
||||
pipe.hpp
|
||||
plain_client.hpp
|
||||
plain_common.hpp
|
||||
plain_server.hpp
|
||||
poll.hpp
|
||||
poller.hpp
|
||||
poller_base.hpp
|
||||
polling_util.hpp
|
||||
pollset.hpp
|
||||
precompiled.hpp
|
||||
proxy.hpp
|
||||
pub.hpp
|
||||
pull.hpp
|
||||
push.hpp
|
||||
radio.hpp
|
||||
random.hpp
|
||||
raw_decoder.hpp
|
||||
raw_encoder.hpp
|
||||
raw_engine.hpp
|
||||
reaper.hpp
|
||||
rep.hpp
|
||||
req.hpp
|
||||
router.hpp
|
||||
scatter.hpp
|
||||
secure_allocator.hpp
|
||||
select.hpp
|
||||
server.hpp
|
||||
session_base.hpp
|
||||
signaler.hpp
|
||||
socket_base.hpp
|
||||
socket_poller.hpp
|
||||
socks.hpp
|
||||
socks_connecter.hpp
|
||||
stdint.hpp
|
||||
stream.hpp
|
||||
stream_engine_base.hpp
|
||||
stream_connecter_base.hpp
|
||||
stream_connecter_base.cpp
|
||||
stream_listener_base.hpp
|
||||
stream_listener_base.cpp
|
||||
sub.hpp
|
||||
tcp.hpp
|
||||
tcp_address.hpp
|
||||
tcp_connecter.hpp
|
||||
tcp_listener.hpp
|
||||
thread.hpp
|
||||
timers.hpp
|
||||
tipc_address.hpp
|
||||
tipc_connecter.hpp
|
||||
tipc_listener.hpp
|
||||
trie.hpp
|
||||
udp_address.hpp
|
||||
udp_engine.hpp
|
||||
v1_decoder.hpp
|
||||
v1_encoder.hpp
|
||||
v2_decoder.hpp
|
||||
v2_encoder.hpp
|
||||
v3_1_encoder.hpp
|
||||
v2_protocol.hpp
|
||||
vmci.hpp
|
||||
vmci_address.hpp
|
||||
vmci_connecter.hpp
|
||||
vmci_listener.hpp
|
||||
windows.hpp
|
||||
wire.hpp
|
||||
xpub.hpp
|
||||
xsub.hpp
|
||||
ypipe.hpp
|
||||
ypipe_base.hpp
|
||||
ypipe_conflate.hpp
|
||||
yqueue.hpp
|
||||
zap_client.hpp
|
||||
zmtp_engine.hpp)
|
||||
|
||||
if(MINGW)
|
||||
# Generate the right type when using -m32 or -m64
|
||||
macro(set_rc_arch rc_target)
|
||||
set(CMAKE_RC_COMPILER_INIT windres)
|
||||
enable_language(RC)
|
||||
set(CMAKE_RC_COMPILE_OBJECT
|
||||
"<CMAKE_RC_COMPILER> <FLAGS> -O coff --target=${rc_target} <DEFINES> -i <SOURCE> -o <OBJECT>")
|
||||
endmacro()
|
||||
|
||||
if(NOT CMAKE_SYSTEM_PROCESSOR)
|
||||
set(CMAKE_SYSTEM_PROCESSOR ${CMAKE_HOST_SYSTEM_PROCESSOR})
|
||||
endif()
|
||||
|
||||
# Also happens on x86_64 systems...what a worthless variable
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "i386"
|
||||
OR CMAKE_SYSTEM_PROCESSOR MATCHES "i486"
|
||||
OR CMAKE_SYSTEM_PROCESSOR MATCHES "i586"
|
||||
OR CMAKE_SYSTEM_PROCESSOR MATCHES "i686"
|
||||
OR CMAKE_SYSTEM_PROCESSOR MATCHES "x86"
|
||||
OR CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64"
|
||||
OR CMAKE_SYSTEM_PROCESSOR MATCHES "amd64")
|
||||
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
set_rc_arch("pe-x86-64")
|
||||
else()
|
||||
set_rc_arch("pe-i386")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(public_headers include/zmq.h include/zmq_utils.h)
|
||||
|
||||
set(readme-docs AUTHORS COPYING COPYING.LESSER NEWS)
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# optional modules
|
||||
|
||||
if(WITH_OPENPGM)
|
||||
add_definitions(-DZMQ_HAVE_OPENPGM)
|
||||
include_directories(${OPENPGM_INCLUDE_DIRS})
|
||||
link_directories(${OPENPGM_LIBRARY_DIRS})
|
||||
set(OPTIONAL_LIBRARIES ${OPENPGM_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(WITH_NORM)
|
||||
find_package(norm)
|
||||
if(norm_FOUND)
|
||||
message(STATUS "Building with NORM")
|
||||
set(ZMQ_HAVE_NORM 1)
|
||||
else()
|
||||
message(FATAL_ERROR "NORM not found")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_VMCI)
|
||||
add_definitions(-DZMQ_HAVE_VMCI)
|
||||
include_directories(${VMCI_INCLUDE_DIRS})
|
||||
list(APPEND cxx-sources vmci_address.cpp vmci_connecter.cpp vmci_listener.cpp vmci.cpp)
|
||||
endif()
|
||||
|
||||
if(ZMQ_HAVE_TIPC)
|
||||
list(APPEND cxx-sources tipc_address.cpp tipc_connecter.cpp tipc_listener.cpp)
|
||||
endif()
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# source generators
|
||||
|
||||
foreach(source ${cxx-sources})
|
||||
list(APPEND sources ${CMAKE_CURRENT_SOURCE_DIR}/src/${source})
|
||||
endforeach()
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/version.rc.in ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
|
||||
|
||||
# Delete any src/platform.hpp left by configure
|
||||
file(REMOVE ${CMAKE_CURRENT_SOURCE_DIR}/src/platform.hpp)
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/builds/cmake/platform.hpp.in ${CMAKE_CURRENT_BINARY_DIR}/platform.hpp)
|
||||
list(APPEND sources ${CMAKE_CURRENT_BINARY_DIR}/platform.hpp)
|
||||
|
||||
set(prefix ${CMAKE_INSTALL_PREFIX})
|
||||
set(exec_prefix ${prefix})
|
||||
set(libdir ${prefix}/lib)
|
||||
set(includedir ${prefix}/include)
|
||||
set(VERSION ${ZMQ_VERSION_MAJOR}.${ZMQ_VERSION_MINOR}.${ZMQ_VERSION_PATCH})
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/libzmq.pc.in ${CMAKE_CURRENT_BINARY_DIR}/libzmq.pc @ONLY)
|
||||
set(zmq-pkgconfig ${CMAKE_CURRENT_BINARY_DIR}/libzmq.pc)
|
||||
|
||||
if(NOT ZMQ_BUILD_FRAMEWORK)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libzmq.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
if(CMAKE_CL_64)
|
||||
set(nsis-template ${CMAKE_CURRENT_SOURCE_DIR}/builds/cmake/NSIS.template64.in)
|
||||
else()
|
||||
set(nsis-template ${CMAKE_CURRENT_SOURCE_DIR}/builds/cmake/NSIS.template32.in)
|
||||
endif()
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/NSIS.template.in
|
||||
COMMAND ${CMAKE_COMMAND} ARGS -E copy ${nsis-template} ${CMAKE_CURRENT_BINARY_DIR}/NSIS.template.in
|
||||
DEPENDS ${nsis-template})
|
||||
endif()
|
||||
|
||||
option(WITH_DOCS "Build html docs" ON)
|
||||
if(WITH_DOCS)
|
||||
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc)
|
||||
file(
|
||||
GLOB docs
|
||||
RELATIVE ${CMAKE_CURRENT_BINARY_DIR}/
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/doc/*.txt")
|
||||
set(html-docs)
|
||||
foreach(txt ${docs})
|
||||
string(REGEX REPLACE ".*/(.*)\\.txt" "\\1.html" html ${txt})
|
||||
set(src ${txt})
|
||||
set(dst doc/${html})
|
||||
if(WITH_DOC)
|
||||
add_custom_command(
|
||||
OUTPUT ${dst}
|
||||
COMMAND ${ASCIIDOC_EXECUTABLE} -d manpage -b xhtml11 -f ${CMAKE_CURRENT_SOURCE_DIR}/doc/asciidoc.conf
|
||||
-azmq_version=${ZMQ_VERSION} -o ${dst} ${src}
|
||||
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${src}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
COMMENT "Generating ${html}")
|
||||
list(APPEND html-docs ${CMAKE_CURRENT_BINARY_DIR}/${dst})
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
if(ZMQ_BUILD_FRAMEWORK)
|
||||
add_custom_command(
|
||||
TARGET libzmq
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} ARGS -E make_directory
|
||||
"${CMAKE_LIBRARY_OUTPUT_PATH}/ZeroMQ.framework/Versions/${ZMQ_VERSION}/MacOS"
|
||||
COMMENT "Perf tools")
|
||||
endif()
|
||||
|
||||
option(ENABLE_PRECOMPILED "Enable precompiled headers, if possible" ON)
|
||||
if(MSVC AND ENABLE_PRECOMPILED)
|
||||
# default for all sources is to use precompiled headers
|
||||
foreach(source ${sources})
|
||||
# C and C++ can not use the same precompiled header
|
||||
if(${source} MATCHES ".cpp$" AND NOT ${source} STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}/src/precompiled.cpp")
|
||||
set_source_files_properties(${source} PROPERTIES COMPILE_FLAGS "/Yuprecompiled.hpp" OBJECT_DEPENDS
|
||||
precompiled.hpp)
|
||||
endif()
|
||||
endforeach()
|
||||
# create precompiled header
|
||||
set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/src/precompiled.cpp
|
||||
PROPERTIES COMPILE_FLAGS "/Ycprecompiled.hpp" OBJECT_OUTPUTS precompiled.hpp)
|
||||
endif()
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# output
|
||||
option(BUILD_SHARED "Whether or not to build the shared object" ON)
|
||||
option(BUILD_STATIC "Whether or not to build the static archive" ON)
|
||||
|
||||
if(MSVC)
|
||||
# Suppress linker warnings caused by #ifdef omission of file content.
|
||||
set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} /ignore:4221")
|
||||
set(PDB_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin")
|
||||
set(PDB_NAME
|
||||
"lib${ZMQ_OUTPUT_BASENAME}${MSVC_TOOLSET}-mt-gd-${ZMQ_VERSION_MAJOR}_${ZMQ_VERSION_MINOR}_${ZMQ_VERSION_PATCH}")
|
||||
function(enable_vs_guideline_checker target)
|
||||
set_target_properties(
|
||||
${target} PROPERTIES VS_GLOBAL_EnableCppCoreCheck true VS_GLOBAL_CodeAnalysisRuleSet CppCoreCheckRules.ruleset
|
||||
VS_GLOBAL_RunCodeAnalysis true)
|
||||
endfunction()
|
||||
if(BUILD_SHARED)
|
||||
add_library(libzmq SHARED ${sources} ${public_headers} ${html-docs} ${readme-docs}
|
||||
${CMAKE_CURRENT_BINARY_DIR}/NSIS.template.in ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
|
||||
if(ENABLE_ANALYSIS)
|
||||
enable_vs_guideline_checker(libzmq)
|
||||
endif()
|
||||
set_target_properties(
|
||||
libzmq
|
||||
PROPERTIES PUBLIC_HEADER "${public_headers}"
|
||||
RELEASE_POSTFIX "${MSVC_TOOLSET}-mt-${ZMQ_VERSION_MAJOR}_${ZMQ_VERSION_MINOR}_${ZMQ_VERSION_PATCH}"
|
||||
RELWITHDEBINFO_POSTFIX
|
||||
"${MSVC_TOOLSET}-mt-${ZMQ_VERSION_MAJOR}_${ZMQ_VERSION_MINOR}_${ZMQ_VERSION_PATCH}"
|
||||
MINSIZEREL_POSTFIX "${MSVC_TOOLSET}-mt-${ZMQ_VERSION_MAJOR}_${ZMQ_VERSION_MINOR}_${ZMQ_VERSION_PATCH}"
|
||||
DEBUG_POSTFIX "${MSVC_TOOLSET}-mt-gd-${ZMQ_VERSION_MAJOR}_${ZMQ_VERSION_MINOR}_${ZMQ_VERSION_PATCH}"
|
||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}"
|
||||
COMPILE_DEFINITIONS "DLL_EXPORT"
|
||||
OUTPUT_NAME "lib${ZMQ_OUTPUT_BASENAME}")
|
||||
if(ZMQ_HAVE_WINDOWS_UWP)
|
||||
set_target_properties(libzmq PROPERTIES LINK_FLAGS_DEBUG "/OPT:NOICF /OPT:NOREF")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(BUILD_STATIC)
|
||||
add_library(libzmq-static STATIC ${sources} ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
|
||||
set_target_properties(
|
||||
libzmq-static
|
||||
PROPERTIES PUBLIC_HEADER "${public_headers}"
|
||||
RELEASE_POSTFIX "${MSVC_TOOLSET}-mt-s-${ZMQ_VERSION_MAJOR}_${ZMQ_VERSION_MINOR}_${ZMQ_VERSION_PATCH}"
|
||||
RELWITHDEBINFO_POSTFIX
|
||||
"${MSVC_TOOLSET}-mt-s-${ZMQ_VERSION_MAJOR}_${ZMQ_VERSION_MINOR}_${ZMQ_VERSION_PATCH}"
|
||||
MINSIZEREL_POSTFIX
|
||||
"${MSVC_TOOLSET}-mt-s-${ZMQ_VERSION_MAJOR}_${ZMQ_VERSION_MINOR}_${ZMQ_VERSION_PATCH}"
|
||||
DEBUG_POSTFIX "${MSVC_TOOLSET}-mt-sgd-${ZMQ_VERSION_MAJOR}_${ZMQ_VERSION_MINOR}_${ZMQ_VERSION_PATCH}"
|
||||
COMPILE_FLAGS "/DZMQ_STATIC"
|
||||
OUTPUT_NAME "lib${ZMQ_OUTPUT_BASENAME}")
|
||||
endif()
|
||||
else()
|
||||
# avoid building everything twice for shared + static only on *nix, as Windows needs different preprocessor defines in
|
||||
# static builds
|
||||
if(NOT MINGW)
|
||||
add_library(objects OBJECT ${sources})
|
||||
set_property(TARGET objects PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||
target_include_directories(
|
||||
objects PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}> $<INSTALL_INTERFACE:include>)
|
||||
endif()
|
||||
|
||||
if(BUILD_SHARED)
|
||||
if(MINGW)
|
||||
add_library(libzmq SHARED ${sources} ${public_headers} ${html-docs} ${readme-docs} ${zmq-pkgconfig}
|
||||
${CMAKE_CURRENT_BINARY_DIR}/version.rc)
|
||||
else()
|
||||
if (CMAKE_GENERATOR STREQUAL "Xcode")
|
||||
add_library(libzmq SHARED ${sources} ${public_headers} ${html-docs} ${readme-docs}
|
||||
${zmq-pkgconfig} ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
|
||||
else()
|
||||
add_library(libzmq SHARED $<TARGET_OBJECTS:objects> ${public_headers} ${html-docs} ${readme-docs}
|
||||
${zmq-pkgconfig} ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
|
||||
endif()
|
||||
|
||||
endif()
|
||||
# NOTE: the SOVERSION and VERSION MUST be the same as the one generated by libtool! It is NOT the same as the
|
||||
# version of the package.
|
||||
set_target_properties(
|
||||
libzmq PROPERTIES COMPILE_DEFINITIONS "DLL_EXPORT" PUBLIC_HEADER "${public_headers}" VERSION "5.2.4"
|
||||
SOVERSION "5" OUTPUT_NAME "${ZMQ_OUTPUT_BASENAME}" PREFIX "lib")
|
||||
if(ZMQ_BUILD_FRAMEWORK)
|
||||
set_target_properties(
|
||||
libzmq
|
||||
PROPERTIES FRAMEWORK TRUE MACOSX_FRAMEWORK_IDENTIFIER "org.zeromq.libzmq" MACOSX_FRAMEWORK_SHORT_VERSION_STRING
|
||||
${ZMQ_VERSION}
|
||||
MACOSX_FRAMEWORK_BUNDLE_VERSION ${ZMQ_VERSION})
|
||||
set_source_files_properties(${html-docs} PROPERTIES MACOSX_PACKAGE_LOCATION doc)
|
||||
set_source_files_properties(${readme-docs} PROPERTIES MACOSX_PACKAGE_LOCATION etc)
|
||||
set_source_files_properties(${zmq-pkgconfig} PROPERTIES MACOSX_PACKAGE_LOCATION lib/pkgconfig)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(BUILD_STATIC)
|
||||
if(MINGW)
|
||||
add_library(libzmq-static STATIC ${sources} ${public_headers} ${html-docs} ${readme-docs} ${zmq-pkgconfig}
|
||||
${CMAKE_CURRENT_BINARY_DIR}/version.rc)
|
||||
else()
|
||||
if (CMAKE_GENERATOR STREQUAL "Xcode")
|
||||
add_library(libzmq-static STATIC ${sources} ${public_headers} ${html-docs} ${readme-docs}
|
||||
${zmq-pkgconfig} ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
|
||||
else()
|
||||
add_library(libzmq-static STATIC $<TARGET_OBJECTS:objects> ${public_headers} ${html-docs} ${readme-docs}
|
||||
${zmq-pkgconfig} ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
|
||||
endif()
|
||||
endif()
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "QNX")
|
||||
target_link_libraries(libzmq-static m)
|
||||
endif()
|
||||
set_target_properties(
|
||||
libzmq-static PROPERTIES PUBLIC_HEADER "${public_headers}" OUTPUT_NAME "${ZMQ_OUTPUT_BASENAME}" PREFIX "lib")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(BUILD_STATIC)
|
||||
target_compile_definitions(libzmq-static PUBLIC ZMQ_STATIC)
|
||||
endif()
|
||||
|
||||
list(APPEND target_outputs "")
|
||||
|
||||
if(BUILD_SHARED)
|
||||
list(APPEND target_outputs "libzmq")
|
||||
endif()
|
||||
|
||||
if(BUILD_STATIC)
|
||||
list(APPEND target_outputs "libzmq-static")
|
||||
endif()
|
||||
|
||||
foreach(target ${target_outputs})
|
||||
target_include_directories(
|
||||
${target} PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}> $<INSTALL_INTERFACE:include>)
|
||||
endforeach()
|
||||
|
||||
if(BUILD_SHARED)
|
||||
target_link_libraries(libzmq ${CMAKE_THREAD_LIBS_INIT})
|
||||
if(GNUTLS_FOUND)
|
||||
target_link_libraries(libzmq ${GNUTLS_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(NSS3_FOUND)
|
||||
target_link_libraries(libzmq ${NSS3_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(LIBBSD_FOUND)
|
||||
target_link_libraries(libzmq ${LIBBSD_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(sodium_FOUND)
|
||||
target_link_libraries(libzmq ${sodium_LIBRARIES})
|
||||
# On Solaris, libsodium depends on libssp
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "SunOS")
|
||||
target_link_libraries(libzmq ssp)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(HAVE_WS2_32)
|
||||
target_link_libraries(libzmq ws2_32)
|
||||
elseif(HAVE_WS2)
|
||||
target_link_libraries(libzmq ws2)
|
||||
endif()
|
||||
|
||||
if(HAVE_RPCRT4)
|
||||
target_link_libraries(libzmq rpcrt4)
|
||||
endif()
|
||||
|
||||
if(HAVE_IPHLAPI)
|
||||
target_link_libraries(libzmq iphlpapi)
|
||||
endif()
|
||||
|
||||
if(RT_LIBRARY)
|
||||
target_link_libraries(libzmq -lrt)
|
||||
endif()
|
||||
|
||||
if(norm_FOUND)
|
||||
target_link_libraries(libzmq norm::norm)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(BUILD_STATIC)
|
||||
target_link_libraries(libzmq-static ${CMAKE_THREAD_LIBS_INIT})
|
||||
if(GNUTLS_FOUND)
|
||||
target_link_libraries(libzmq-static ${GNUTLS_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(LIBBSD_FOUND)
|
||||
target_link_libraries(libzmq-static ${LIBBSD_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(NSS3_FOUND)
|
||||
target_link_libraries(libzmq-static ${NSS3_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(SODIUM_FOUND)
|
||||
target_link_libraries(libzmq-static ${SODIUM_LIBRARIES})
|
||||
# On Solaris, libsodium depends on libssp
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "SunOS")
|
||||
target_link_libraries(libzmq-static ssp)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(HAVE_WS2_32)
|
||||
target_link_libraries(libzmq-static ws2_32)
|
||||
elseif(HAVE_WS2)
|
||||
target_link_libraries(libzmq-static ws2)
|
||||
endif()
|
||||
|
||||
if(HAVE_RPCRT4)
|
||||
target_link_libraries(libzmq-static rpcrt4)
|
||||
endif()
|
||||
|
||||
if(HAVE_IPHLAPI)
|
||||
target_link_libraries(libzmq-static iphlpapi)
|
||||
endif()
|
||||
|
||||
if(RT_LIBRARY)
|
||||
target_link_libraries(libzmq-static -lrt)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "QNX")
|
||||
add_definitions(-DUNITY_EXCLUDE_MATH_H)
|
||||
endif()
|
||||
|
||||
if(norm_FOUND)
|
||||
target_link_libraries(libzmq-static norm::norm)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(BUILD_SHARED)
|
||||
set(perf-tools
|
||||
local_lat
|
||||
remote_lat
|
||||
local_thr
|
||||
remote_thr
|
||||
inproc_lat
|
||||
inproc_thr
|
||||
proxy_thr)
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug") # Why?
|
||||
option(WITH_PERF_TOOL "Build with perf-tools" ON)
|
||||
else()
|
||||
option(WITH_PERF_TOOL "Build with perf-tools" OFF)
|
||||
endif()
|
||||
|
||||
if(WITH_PERF_TOOL)
|
||||
foreach(perf-tool ${perf-tools})
|
||||
add_executable(${perf-tool} perf/${perf-tool}.cpp)
|
||||
target_link_libraries(${perf-tool} libzmq)
|
||||
|
||||
if(GNUTLS_FOUND)
|
||||
target_link_libraries(${perf-tool} ${GNUTLS_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(LIBBSD_FOUND)
|
||||
target_link_libraries(${perf-tool} ${LIBBSD_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(NSS3_FOUND)
|
||||
target_link_libraries(${perf-tool} ${NSS3_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(SODIUM_FOUND)
|
||||
target_link_libraries(${perf-tool} ${SODIUM_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(ZMQ_BUILD_FRAMEWORK)
|
||||
# Copy perf-tools binaries into Framework
|
||||
add_custom_command(
|
||||
TARGET libzmq
|
||||
${perf-tool} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} ARGS -E copy "$<TARGET_FILE:${perf-tool}>"
|
||||
"${LIBRARY_OUTPUT_PATH}/ZeroMQ.framework/Versions/${ZMQ_VERSION_STRING}/MacOS/${perf-tool}"
|
||||
VERBATIM
|
||||
COMMENT "Perf tools")
|
||||
else()
|
||||
install(TARGETS ${perf-tool} RUNTIME DESTINATION bin COMPONENT PerfTools)
|
||||
endif()
|
||||
if(ZMQ_HAVE_WINDOWS_UWP)
|
||||
set_target_properties(${perf-tool} PROPERTIES LINK_FLAGS_DEBUG "/OPT:NOICF /OPT:NOREF")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(BUILD_STATIC)
|
||||
add_executable(benchmark_radix_tree perf/benchmark_radix_tree.cpp)
|
||||
target_link_libraries(benchmark_radix_tree libzmq-static)
|
||||
target_include_directories(benchmark_radix_tree PUBLIC "${CMAKE_CURRENT_LIST_DIR}/src")
|
||||
if(ZMQ_HAVE_WINDOWS_UWP)
|
||||
set_target_properties(benchmark_radix_tree PROPERTIES LINK_FLAGS_DEBUG "/OPT:NOICF /OPT:NOREF")
|
||||
endif()
|
||||
endif()
|
||||
elseif(WITH_PERF_TOOL)
|
||||
message(FATAL_ERROR "Shared library disabled - perf-tools unavailable.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# tests
|
||||
|
||||
option(BUILD_TESTS "Whether or not to build the tests" ON)
|
||||
|
||||
set(ZMQ_BUILD_TESTS
|
||||
${BUILD_TESTS}
|
||||
CACHE BOOL "Build the tests for ZeroMQ")
|
||||
|
||||
if(ZMQ_BUILD_TESTS)
|
||||
enable_testing() # Enable testing only works in root scope
|
||||
add_subdirectory(tests)
|
||||
if(BUILD_STATIC)
|
||||
add_subdirectory(unittests)
|
||||
else()
|
||||
message(WARNING "Not building unit tests, since BUILD_STATIC is not enabled")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# installer
|
||||
|
||||
if(MSVC AND (BUILD_SHARED OR BUILD_STATIC))
|
||||
install(
|
||||
TARGETS ${target_outputs}
|
||||
EXPORT ${PROJECT_NAME}-targets
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} COMPONENT SDK)
|
||||
if(MSVC_IDE)
|
||||
install(
|
||||
FILES ${PDB_OUTPUT_DIRECTORY}/\${CMAKE_INSTALL_CONFIG_NAME}/${PDB_NAME}.pdb
|
||||
DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
COMPONENT SDK
|
||||
OPTIONAL)
|
||||
else()
|
||||
install(
|
||||
FILES ${PDB_OUTPUT_DIRECTORY}/${PDB_NAME}.pdb
|
||||
DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
COMPONENT SDK
|
||||
OPTIONAL)
|
||||
endif()
|
||||
if(BUILD_SHARED)
|
||||
install(
|
||||
TARGETS libzmq
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} COMPONENT Runtime)
|
||||
endif()
|
||||
elseif(BUILD_SHARED OR BUILD_STATIC)
|
||||
install(
|
||||
TARGETS ${target_outputs}
|
||||
EXPORT ${PROJECT_NAME}-targets
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
FRAMEWORK DESTINATION "Library/Frameworks"
|
||||
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
endif()
|
||||
|
||||
foreach(readme ${readme-docs})
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${readme} ${CMAKE_CURRENT_BINARY_DIR}/${readme}.txt)
|
||||
|
||||
if(NOT ZMQ_BUILD_FRAMEWORK)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${readme}.txt DESTINATION share/zmq)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(WITH_DOC)
|
||||
if(NOT ZMQ_BUILD_FRAMEWORK)
|
||||
install(
|
||||
FILES ${html-docs}
|
||||
DESTINATION doc/zmq
|
||||
COMPONENT RefGuide)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
set(ZEROMQ_CMAKECONFIG_INSTALL_DIR
|
||||
"CMake"
|
||||
CACHE STRING "install path for ZeroMQConfig.cmake")
|
||||
else()
|
||||
# CMake search path wants either "share" (AKA GNUInstallDirs DATAROOTDIR) for arch-independent, or LIBDIR for arch-
|
||||
# dependent, plus "cmake" as prefix
|
||||
set(ZEROMQ_CMAKECONFIG_INSTALL_DIR
|
||||
"${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
|
||||
CACHE STRING "install path for ZeroMQConfig.cmake")
|
||||
endif()
|
||||
|
||||
if((NOT CMAKE_VERSION VERSION_LESS 3.0) AND (BUILD_SHARED OR BUILD_STATIC))
|
||||
export(EXPORT ${PROJECT_NAME}-targets FILE "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Targets.cmake")
|
||||
endif()
|
||||
configure_package_config_file(
|
||||
builds/cmake/${PROJECT_NAME}Config.cmake.in "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
|
||||
INSTALL_DESTINATION ${ZEROMQ_CMAKECONFIG_INSTALL_DIR})
|
||||
write_basic_package_version_file(
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
|
||||
VERSION ${ZMQ_VERSION_MAJOR}.${ZMQ_VERSION_MINOR}.${ZMQ_VERSION_PATCH}
|
||||
COMPATIBILITY AnyNewerVersion)
|
||||
if(BUILD_SHARED OR BUILD_STATIC)
|
||||
install(
|
||||
EXPORT ${PROJECT_NAME}-targets
|
||||
FILE ${PROJECT_NAME}Targets.cmake
|
||||
DESTINATION ${ZEROMQ_CMAKECONFIG_INSTALL_DIR})
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
|
||||
DESTINATION ${ZEROMQ_CMAKECONFIG_INSTALL_DIR})
|
||||
endif()
|
||||
|
||||
option(ENABLE_CPACK "Enables cpack rules" ON)
|
||||
if(MSVC AND ENABLE_CPACK)
|
||||
if(${CMAKE_BUILD_TYPE} MATCHES "Debug")
|
||||
set(CMAKE_INSTALL_DEBUG_LIBRARIES_ONLY TRUE)
|
||||
set(CMAKE_INSTALL_DEBUG_LIBRARIES TRUE)
|
||||
set(CMAKE_INSTALL_UCRT_LIBRARIES TRUE)
|
||||
endif()
|
||||
include(InstallRequiredSystemLibraries)
|
||||
|
||||
if(CMAKE_CL_64)
|
||||
set(arch_name "x64")
|
||||
else()
|
||||
set(arch_name "x86")
|
||||
endif()
|
||||
|
||||
set(CPACK_NSIS_DISPLAY_NAME "ZeroMQ ${ZMQ_VERSION_MAJOR}.${ZMQ_VERSION_MINOR}.${ZMQ_VERSION_PATCH}(${arch_name})")
|
||||
set(CPACK_PACKAGE_FILE_NAME "ZeroMQ-${ZMQ_VERSION_MAJOR}.${ZMQ_VERSION_MINOR}.${ZMQ_VERSION_PATCH}-${arch_name}")
|
||||
|
||||
# TODO: I think this part was intended to be used when running cpack separately from cmake but I don't know how that
|
||||
# works.
|
||||
#
|
||||
# macro(add_crt_version version) set(rel_dir
|
||||
# "${CMAKE_CURRENT_BINARY_DIR}/build/${arch_name}/${version};ZeroMQ;ALL;/")
|
||||
# set(debug_dir
|
||||
# "${CMAKE_CURRENT_BINARY_DIR}/debug/${arch_name}/${version};ZeroMQ;ALL;/")
|
||||
# if(EXISTS ${rel_dir}) list(APPEND CPACK_INSTALL_CMAKE_PROJECTS ${rel_dir}) endif()
|
||||
|
||||
# if(EXISTS ${debug_dir}) list(APPEND CPACK_INSTALL_CMAKE_PROJECTS ${rel_dir}) endmacro() endmacro()
|
||||
|
||||
# add_crt_version(v110) add_crt_version(v100) add_crt_version(v90)
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_BINARY_DIR})
|
||||
set(CPACK_GENERATOR "NSIS")
|
||||
set(CPACK_PACKAGE_NAME "ZeroMQ")
|
||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "ZeroMQ lightweight messaging kernel")
|
||||
set(CPACK_PACKAGE_VENDOR "Miru")
|
||||
set(CPACK_NSIS_CONTACT "Steven McCoy <Steven.McCoy@miru.hk>")
|
||||
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_BINARY_DIR}\\\\COPYING.txt")
|
||||
# set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_BINARY_DIR}\\\\README.txt") set(CPACK_RESOURCE_FILE_WELCOME
|
||||
# "${CMAKE_CURRENT_BINARY_DIR}\\\\WELCOME.txt") There is a bug in NSI that does not handle full unix paths properly.
|
||||
# Make sure there is at least one set of four(4) backslashes.
|
||||
set(CPACK_NSIS_MUI_ICON "${CMAKE_CURRENT_SOURCE_DIR}\\\\installer.ico")
|
||||
set(CPACK_NSIS_MUI_UNIICON "${CMAKE_CURRENT_SOURCE_DIR}\\\\installer.ico")
|
||||
|
||||
set(CPACK_PACKAGE_ICON "${CMAKE_CURRENT_SOURCE_DIR}\\\\branding.bmp")
|
||||
set(CPACK_NSIS_COMPRESSOR "/SOLID lzma")
|
||||
set(CPACK_PACKAGE_VERSION ${ZMQ_VERSION})
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR ${ZMQ_VERSION_MAJOR})
|
||||
set(CPACK_PACKAGE_VERSION_MINOR ${ZMQ_VERSION_MINOR})
|
||||
set(CPACK_PACKAGE_VERSION_PATCH ${ZMQ_VERSION_PATCH})
|
||||
# set(CPACK_PACKAGE_INSTALL_DIRECTORY "ZMQ Install Directory") set(CPACK_TEMPORARY_DIRECTORY "ZMQ Temporary CPack
|
||||
# Directory")
|
||||
|
||||
include(CPack)
|
||||
|
||||
cpack_add_component_group(Development DISPLAY_NAME "ZeroMQ software development kit" EXPANDED)
|
||||
cpack_add_component(PerfTools DISPLAY_NAME "ZeroMQ performance tools" INSTALL_TYPES FullInstall DevInstall)
|
||||
cpack_add_component(SourceCode DISPLAY_NAME "ZeroMQ source code" DISABLED INSTALL_TYPES FullInstall)
|
||||
cpack_add_component(
|
||||
SDK
|
||||
DISPLAY_NAME
|
||||
"ZeroMQ headers and libraries"
|
||||
INSTALL_TYPES
|
||||
FullInstall
|
||||
DevInstall
|
||||
GROUP
|
||||
Development)
|
||||
if(WITH_DOC)
|
||||
cpack_add_component(
|
||||
RefGuide
|
||||
DISPLAY_NAME
|
||||
"ZeroMQ reference guide"
|
||||
INSTALL_TYPES
|
||||
FullInstall
|
||||
DevInstall
|
||||
GROUP
|
||||
Development)
|
||||
endif()
|
||||
cpack_add_component(
|
||||
Runtime
|
||||
DISPLAY_NAME
|
||||
"ZeroMQ runtime files"
|
||||
REQUIRED
|
||||
INSTALL_TYPES
|
||||
FullInstall
|
||||
DevInstall
|
||||
MinInstall)
|
||||
cpack_add_install_type(FullInstall DISPLAY_NAME "Full install, including source code")
|
||||
cpack_add_install_type(DevInstall DISPLAY_NAME "Developer install, headers and libraries")
|
||||
cpack_add_install_type(MinInstall DISPLAY_NAME "Minimal install, runtime only")
|
||||
endif()
|
||||
|
||||
# Export this for library to help build this as a sub-project
|
||||
set(ZEROMQ_LIBRARY
|
||||
libzmq
|
||||
CACHE STRING "ZeroMQ library")
|
||||
|
||||
# Workaround for MSVS10 to avoid the Dialog Hell FIXME: This could be removed with future version of CMake.
|
||||
if(MSVC_VERSION EQUAL 1600)
|
||||
set(ZMQ_SLN_FILENAME "${CMAKE_CURRENT_BINARY_DIR}/ZeroMQ.sln")
|
||||
if(EXISTS "${ZMQ_SLN_FILENAME}")
|
||||
file(APPEND "${ZMQ_SLN_FILENAME}" "\n# This should be regenerated!\n")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# this cannot be moved, as it does not only contain function/macro definitions
|
||||
option(ENABLE_CLANG "Include Clang" ON)
|
||||
if (ENABLE_CLANG)
|
||||
include(ClangFormat)
|
||||
endif()
|
||||
|
||||
# fixes https://github.com/zeromq/libzmq/issues/3776 The problem is, both libzmq-static libzmq try to use/generate
|
||||
# precompiled.pch at the same time Add a dependency, so they run in order and so they dont get in each others way TODO
|
||||
# still generates warning "build\x64-Debug\ninja : warning : multiple rules generate precompiled.hpp. builds involving
|
||||
# this target will not be correct; continuing anyway [-w dupbuild=warn]"
|
||||
if(MSVC
|
||||
AND ENABLE_PRECOMPILED
|
||||
AND BUILD_SHARED
|
||||
AND BUILD_STATIC)
|
||||
add_dependencies(libzmq-static libzmq)
|
||||
endif()
|
||||
674
3rd/libzmq/COPYING
Normal file
674
3rd/libzmq/COPYING
Normal file
@@ -0,0 +1,674 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||
181
3rd/libzmq/COPYING.LESSER
Normal file
181
3rd/libzmq/COPYING.LESSER
Normal file
@@ -0,0 +1,181 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
SPECIAL EXCEPTION GRANTED BY COPYRIGHT HOLDERS
|
||||
|
||||
As a special exception, copyright holders give you permission to link this
|
||||
library with independent modules to produce an executable, regardless of
|
||||
the license terms of these independent modules, and to copy and distribute
|
||||
the resulting executable under terms of your choice, provided that you also
|
||||
meet, for each linked independent module, the terms and conditions of
|
||||
the license of that module. An independent module is a module which is not
|
||||
derived from or based on this library. If you modify this library, you must
|
||||
extend this exception to your version of the library.
|
||||
|
||||
Note: this exception relieves you of any obligations under sections 4 and 5
|
||||
of this license, and section 6 of the GNU General Public License.
|
||||
485
3rd/libzmq/Jenkinsfile
vendored
Normal file
485
3rd/libzmq/Jenkinsfile
vendored
Normal file
@@ -0,0 +1,485 @@
|
||||
pipeline {
|
||||
agent { label "linux || macosx || bsd || solaris || posix || windows" }
|
||||
parameters {
|
||||
// Use DEFAULT_DEPLOY_BRANCH_PATTERN and DEFAULT_DEPLOY_JOB_NAME if
|
||||
// defined in this jenkins setup -- in Jenkins Management Web-GUI
|
||||
// see Configure System / Global properties / Environment variables
|
||||
// Default (if unset) is empty => no deployment attempt after good test
|
||||
// See zproject Jenkinsfile-deploy.example for an example deploy job.
|
||||
// TODO: Try to marry MultiBranchPipeline support with pre-set defaults
|
||||
// directly in MultiBranchPipeline plugin, or mechanism like Credentials,
|
||||
// or a config file uploaded to master for all jobs or this job, see
|
||||
// https://jenkins.io/doc/pipeline/examples/#configfile-provider-plugin
|
||||
string (
|
||||
defaultValue: '${DEFAULT_DEPLOY_BRANCH_PATTERN}',
|
||||
description: 'Regular expression of branch names for which a deploy action would be attempted after a successful build and test; leave empty to not deploy. Reasonable value is ^(master|release/.*|feature/*)$',
|
||||
name : 'DEPLOY_BRANCH_PATTERN')
|
||||
string (
|
||||
defaultValue: '${DEFAULT_DEPLOY_JOB_NAME}',
|
||||
description: 'Name of your job that handles deployments and should accept arguments: DEPLOY_GIT_URL DEPLOY_GIT_BRANCH DEPLOY_GIT_COMMIT -- and it is up to that job what to do with this knowledge (e.g. git archive + push to packaging); leave empty to not deploy',
|
||||
name : 'DEPLOY_JOB_NAME')
|
||||
booleanParam (
|
||||
defaultValue: true,
|
||||
description: 'If the deployment is done, should THIS job wait for it to complete and include its success or failure as the build result (true), or should it schedule the job and exit quickly to free up the executor (false)',
|
||||
name: 'DEPLOY_REPORT_RESULT')
|
||||
booleanParam (
|
||||
defaultValue: true,
|
||||
description: 'Attempt stable build without DRAFT API in this run?',
|
||||
name: 'DO_BUILD_WITHOUT_DRAFT_API')
|
||||
booleanParam (
|
||||
defaultValue: true,
|
||||
description: 'Attempt build with DRAFT API in this run?',
|
||||
name: 'DO_BUILD_WITH_DRAFT_API')
|
||||
booleanParam (
|
||||
defaultValue: true,
|
||||
description: 'Attempt a build with docs in this run? (Note: corresponding tools are required in the build environment)',
|
||||
name: 'DO_BUILD_DOCS')
|
||||
booleanParam (
|
||||
defaultValue: false,
|
||||
description: 'Publish as an archive a "dist" tarball from a build with docs in this run? (Note: corresponding tools are required in the build environment; enabling this enforces DO_BUILD_DOCS too)',
|
||||
name: 'DO_DIST_DOCS')
|
||||
booleanParam (
|
||||
defaultValue: true,
|
||||
description: 'Attempt "make check" in this run?',
|
||||
name: 'DO_TEST_CHECK')
|
||||
booleanParam (
|
||||
defaultValue: false,
|
||||
description: 'Attempt "make memcheck" in this run?',
|
||||
name: 'DO_TEST_MEMCHECK')
|
||||
booleanParam (
|
||||
defaultValue: true,
|
||||
description: 'Attempt "make distcheck" in this run?',
|
||||
name: 'DO_TEST_DISTCHECK')
|
||||
booleanParam (
|
||||
defaultValue: true,
|
||||
description: 'Attempt a "make install" check in this run?',
|
||||
name: 'DO_TEST_INSTALL')
|
||||
string (
|
||||
defaultValue: "`pwd`/tmp/_inst",
|
||||
description: 'If attempting a "make install" check in this run, what DESTDIR to specify? (absolute path, defaults to "BUILD_DIR/tmp/_inst")',
|
||||
name: 'USE_TEST_INSTALL_DESTDIR')
|
||||
booleanParam (
|
||||
defaultValue: true,
|
||||
description: 'Attempt "cppcheck" analysis before this run? (Note: corresponding tools are required in the build environment)',
|
||||
name: 'DO_CPPCHECK')
|
||||
booleanParam (
|
||||
defaultValue: true,
|
||||
description: 'Require that there are no files not discovered changed/untracked via .gitignore after builds and tests?',
|
||||
name: 'REQUIRE_GOOD_GITIGNORE')
|
||||
string (
|
||||
defaultValue: "30",
|
||||
description: 'When running tests, use this timeout (in minutes; be sure to leave enough for double-job of a distcheck too)',
|
||||
name: 'USE_TEST_TIMEOUT')
|
||||
booleanParam (
|
||||
defaultValue: true,
|
||||
description: 'When using temporary subdirs in build/test workspaces, wipe them after successful builds?',
|
||||
name: 'DO_CLEANUP_AFTER_BUILD')
|
||||
}
|
||||
triggers {
|
||||
pollSCM 'H/2 * * * *'
|
||||
}
|
||||
// Note: your Jenkins setup may benefit from similar setup on side of agents:
|
||||
// PATH="/usr/lib64/ccache:/usr/lib/ccache:/usr/bin:/bin:${PATH}"
|
||||
stages {
|
||||
stage ('prepare') {
|
||||
steps {
|
||||
dir("tmp") {
|
||||
sh 'if [ -s Makefile ]; then make -k distclean || true ; fi'
|
||||
sh 'chmod -R u+w .'
|
||||
deleteDir()
|
||||
}
|
||||
sh './autogen.sh'
|
||||
stash (name: 'prepped', includes: '**/*', excludes: '**/cppcheck.xml')
|
||||
}
|
||||
}
|
||||
stage ('compile') {
|
||||
parallel {
|
||||
stage ('build with DRAFT') {
|
||||
when { expression { return ( params.DO_BUILD_WITH_DRAFT_API ) } }
|
||||
steps {
|
||||
dir("tmp/build-withDRAFT") {
|
||||
deleteDir()
|
||||
unstash 'prepped'
|
||||
sh 'CCACHE_BASEDIR="`pwd`" ; export CCACHE_BASEDIR; ./configure --enable-drafts=yes --with-docs=no'
|
||||
sh 'CCACHE_BASEDIR="`pwd`" ; export CCACHE_BASEDIR; make -k -j4 || make'
|
||||
sh 'echo "Are GitIgnores good after make with drafts? (should have no output below)"; git status -s || if [ "${params.REQUIRE_GOOD_GITIGNORE}" = false ]; then echo "WARNING GitIgnore tests found newly changed or untracked files" >&2 ; exit 0 ; else echo "FAILED GitIgnore tests" >&2 ; exit 1; fi'
|
||||
stash (name: 'built-draft', includes: '**/*', excludes: '**/cppcheck.xml')
|
||||
script {
|
||||
if ( params.DO_CLEANUP_AFTER_BUILD ) {
|
||||
deleteDir()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage ('build without DRAFT') {
|
||||
when { expression { return ( params.DO_BUILD_WITHOUT_DRAFT_API ) } }
|
||||
steps {
|
||||
dir("tmp/build-withoutDRAFT") {
|
||||
deleteDir()
|
||||
unstash 'prepped'
|
||||
sh 'CCACHE_BASEDIR="`pwd`" ; export CCACHE_BASEDIR; ./configure --enable-drafts=no --with-docs=no'
|
||||
sh 'CCACHE_BASEDIR="`pwd`" ; export CCACHE_BASEDIR; make -k -j4 || make'
|
||||
sh 'echo "Are GitIgnores good after make without drafts? (should have no output below)"; git status -s || if [ "${params.REQUIRE_GOOD_GITIGNORE}" = false ]; then echo "WARNING GitIgnore tests found newly changed or untracked files" >&2 ; exit 0 ; else echo "FAILED GitIgnore tests" >&2 ; exit 1; fi'
|
||||
stash (name: 'built-nondraft', includes: '**/*', excludes: '**/cppcheck.xml')
|
||||
script {
|
||||
if ( params.DO_CLEANUP_AFTER_BUILD ) {
|
||||
deleteDir()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage ('build with DOCS') {
|
||||
when { expression { return ( params.DO_BUILD_DOCS || params.DO_DIST_DOCS ) } }
|
||||
steps {
|
||||
dir("tmp/build-DOCS") {
|
||||
deleteDir()
|
||||
unstash 'prepped'
|
||||
sh 'CCACHE_BASEDIR="`pwd`" ; export CCACHE_BASEDIR; ./configure --enable-drafts=yes --with-docs=yes'
|
||||
script {
|
||||
if ( params.DO_DIST_DOCS ) {
|
||||
sh 'CCACHE_BASEDIR="`pwd`" ; export CCACHE_BASEDIR; make dist-gzip || exit ; DISTFILE="`ls -1tc *.tar.gz | head -1`" && [ -n "$DISTFILE" ] && [ -s "$DISTFILE" ] || exit ; mv -f "$DISTFILE" __dist.tar.gz'
|
||||
archiveArtifacts artifacts: '__dist.tar.gz'
|
||||
sh "rm -f __dist.tar.gz"
|
||||
}
|
||||
}
|
||||
sh 'CCACHE_BASEDIR="`pwd`" ; export CCACHE_BASEDIR; make -k -j4 || make'
|
||||
sh 'echo "Are GitIgnores good after make with docs? (should have no output below)"; git status -s || if [ "${params.REQUIRE_GOOD_GITIGNORE}" = false ]; then echo "WARNING GitIgnore tests found newly changed or untracked files" >&2 ; exit 0 ; else echo "FAILED GitIgnore tests" >&2 ; exit 1; fi'
|
||||
stash (name: 'built-docs', includes: '**/*', excludes: '**/cppcheck.xml')
|
||||
script {
|
||||
if ( params.DO_CLEANUP_AFTER_BUILD ) {
|
||||
deleteDir()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage ('check') {
|
||||
parallel {
|
||||
stage ('cppcheck') {
|
||||
when { expression { return ( params.DO_CPPCHECK ) } }
|
||||
steps {
|
||||
dir("tmp/test-cppcheck") {
|
||||
deleteDir()
|
||||
unstash 'prepped'
|
||||
sh 'cppcheck --std=c++11 --enable=all --inconclusive --xml --xml-version=2 . 2>cppcheck.xml'
|
||||
archiveArtifacts artifacts: '**/cppcheck.xml'
|
||||
sh 'rm -f cppcheck.xml'
|
||||
script {
|
||||
if ( params.DO_CLEANUP_AFTER_BUILD ) {
|
||||
deleteDir()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage ('check with DRAFT') {
|
||||
when { expression { return ( params.DO_BUILD_WITH_DRAFT_API && params.DO_TEST_CHECK ) } }
|
||||
steps {
|
||||
dir("tmp/test-check-withDRAFT") {
|
||||
deleteDir()
|
||||
unstash 'built-draft'
|
||||
script {
|
||||
def RETRY_NUMBER = 0
|
||||
retry(3) {
|
||||
RETRY_NUMBER++
|
||||
timeout (time: "${params.USE_TEST_TIMEOUT}".toInteger(), unit: 'MINUTES') {
|
||||
try {
|
||||
sh 'CCACHE_BASEDIR="`pwd`" ; export CCACHE_BASEDIR; LD_LIBRARY_PATH="`pwd`/src/.libs:$LD_LIBRARY_PATH"; export LD_LIBRARY_PATH; make LD_LIBRARY_PATH="$LD_LIBRARY_PATH" check'
|
||||
}
|
||||
catch (Exception e) {
|
||||
currentBuild.result = 'UNSTABLE' // Jenkins should not let the verdict "improve"
|
||||
sh """D="`pwd`"; B="`basename "\$D"`" ; [ "${RETRY_NUMBER}" -gt 0 ] && T="_try-${RETRY_NUMBER}" || T="" ; tar czf "test-suite_${BUILD_TAG}_\${B}\${T}.tar.gz" `find . -name '*.trs'` `find . -name '*.log'`"""
|
||||
archiveArtifacts artifacts: "**/test-suite*.tar.gz", allowEmpty: true
|
||||
throw e
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
sh 'echo "Are GitIgnores good after make check with drafts? (should have no output below)"; git status -s || if [ "${params.REQUIRE_GOOD_GITIGNORE}" = false ]; then echo "WARNING GitIgnore tests found newly changed or untracked files" >&2 ; exit 0 ; else echo "FAILED GitIgnore tests" >&2 ; exit 1; fi'
|
||||
script {
|
||||
if ( params.DO_CLEANUP_AFTER_BUILD ) {
|
||||
deleteDir()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage ('check without DRAFT') {
|
||||
when { expression { return ( params.DO_BUILD_WITHOUT_DRAFT_API && params.DO_TEST_CHECK ) } }
|
||||
steps {
|
||||
dir("tmp/test-check-withoutDRAFT") {
|
||||
deleteDir()
|
||||
unstash 'built-nondraft'
|
||||
script {
|
||||
def RETRY_NUMBER = 0
|
||||
retry(3) {
|
||||
RETRY_NUMBER++
|
||||
timeout (time: "${params.USE_TEST_TIMEOUT}".toInteger(), unit: 'MINUTES') {
|
||||
try {
|
||||
sh 'CCACHE_BASEDIR="`pwd`" ; export CCACHE_BASEDIR; LD_LIBRARY_PATH="`pwd`/src/.libs:$LD_LIBRARY_PATH"; export LD_LIBRARY_PATH; make LD_LIBRARY_PATH="$LD_LIBRARY_PATH" check'
|
||||
}
|
||||
catch (Exception e) {
|
||||
currentBuild.result = 'UNSTABLE' // Jenkins should not let the verdict "improve"
|
||||
sh """D="`pwd`"; B="`basename "\$D"`" ; [ "${RETRY_NUMBER}" -gt 0 ] && T="_try-${RETRY_NUMBER}" || T="" ; tar czf "test-suite_${BUILD_TAG}_\${B}\${T}.tar.gz" `find . -name '*.trs'` `find . -name '*.log'`"""
|
||||
archiveArtifacts artifacts: "**/test-suite*.tar.gz", allowEmpty: true
|
||||
throw e
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
sh 'echo "Are GitIgnores good after make check without drafts? (should have no output below)"; git status -s || if [ "${params.REQUIRE_GOOD_GITIGNORE}" = false ]; then echo "WARNING GitIgnore tests found newly changed or untracked files" >&2 ; exit 0 ; else echo "FAILED GitIgnore tests" >&2 ; exit 1; fi'
|
||||
script {
|
||||
if ( params.DO_CLEANUP_AFTER_BUILD ) {
|
||||
deleteDir()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage ('memcheck with DRAFT') {
|
||||
when { expression { return ( params.DO_BUILD_WITH_DRAFT_API && params.DO_TEST_MEMCHECK ) } }
|
||||
steps {
|
||||
dir("tmp/test-memcheck-withDRAFT") {
|
||||
deleteDir()
|
||||
unstash 'built-draft'
|
||||
script {
|
||||
def RETRY_NUMBER = 0
|
||||
retry(3) {
|
||||
RETRY_NUMBER++
|
||||
timeout (time: "${params.USE_TEST_TIMEOUT}".toInteger(), unit: 'MINUTES') {
|
||||
try {
|
||||
sh 'CCACHE_BASEDIR="`pwd`" ; export CCACHE_BASEDIR; LD_LIBRARY_PATH="`pwd`/src/.libs:$LD_LIBRARY_PATH"; export LD_LIBRARY_PATH; make LD_LIBRARY_PATH="$LD_LIBRARY_PATH" memcheck && exit 0 ; echo "Re-running failed ($?) memcheck with greater verbosity" >&2 ; make LD_LIBRARY_PATH="$LD_LIBRARY_PATH" VERBOSE=1 memcheck-verbose'
|
||||
}
|
||||
catch (Exception e) {
|
||||
currentBuild.result = 'UNSTABLE' // Jenkins should not let the verdict "improve"
|
||||
sh """D="`pwd`"; B="`basename "\$D"`" ; [ "${RETRY_NUMBER}" -gt 0 ] && T="_try-${RETRY_NUMBER}" || T="" ; tar czf "test-suite_${BUILD_TAG}_\${B}\${T}.tar.gz" `find . -name '*.trs'` `find . -name '*.log'`"""
|
||||
archiveArtifacts artifacts: "**/test-suite*.tar.gz", allowEmpty: true
|
||||
throw e
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
sh 'echo "Are GitIgnores good after make memcheck with drafts? (should have no output below)"; git status -s || if [ "${params.REQUIRE_GOOD_GITIGNORE}" = false ]; then echo "WARNING GitIgnore tests found newly changed or untracked files" >&2 ; exit 0 ; else echo "FAILED GitIgnore tests" >&2 ; exit 1; fi'
|
||||
script {
|
||||
if ( params.DO_CLEANUP_AFTER_BUILD ) {
|
||||
deleteDir()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage ('memcheck without DRAFT') {
|
||||
when { expression { return ( params.DO_BUILD_WITHOUT_DRAFT_API && params.DO_TEST_MEMCHECK ) } }
|
||||
steps {
|
||||
dir("tmp/test-memcheck-withoutDRAFT") {
|
||||
deleteDir()
|
||||
unstash 'built-nondraft'
|
||||
script {
|
||||
def RETRY_NUMBER = 0
|
||||
retry(3) {
|
||||
RETRY_NUMBER++
|
||||
timeout (time: "${params.USE_TEST_TIMEOUT}".toInteger(), unit: 'MINUTES') {
|
||||
try {
|
||||
sh 'CCACHE_BASEDIR="`pwd`" ; export CCACHE_BASEDIR; LD_LIBRARY_PATH="`pwd`/src/.libs:$LD_LIBRARY_PATH"; export LD_LIBRARY_PATH; make LD_LIBRARY_PATH="$LD_LIBRARY_PATH" memcheck && exit 0 ; echo "Re-running failed ($?) memcheck with greater verbosity" >&2 ; make LD_LIBRARY_PATH="$LD_LIBRARY_PATH" VERBOSE=1 memcheck-verbose'
|
||||
}
|
||||
catch (Exception e) {
|
||||
currentBuild.result = 'UNSTABLE' // Jenkins should not let the verdict "improve"
|
||||
sh """D="`pwd`"; B="`basename "\$D"`" ; [ "${RETRY_NUMBER}" -gt 0 ] && T="_try-${RETRY_NUMBER}" || T="" ; tar czf "test-suite_${BUILD_TAG}_\${B}\${T}.tar.gz" `find . -name '*.trs'` `find . -name '*.log'`"""
|
||||
archiveArtifacts artifacts: "**/test-suite*.tar.gz", allowEmpty: true
|
||||
throw e
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
sh 'echo "Are GitIgnores good after make memcheck without drafts? (should have no output below)"; git status -s || if [ "${params.REQUIRE_GOOD_GITIGNORE}" = false ]; then echo "WARNING GitIgnore tests found newly changed or untracked files" >&2 ; exit 0 ; else echo "FAILED GitIgnore tests" >&2 ; exit 1; fi'
|
||||
script {
|
||||
if ( params.DO_CLEANUP_AFTER_BUILD ) {
|
||||
deleteDir()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage ('distcheck with DRAFT') {
|
||||
when { expression { return ( params.DO_BUILD_WITH_DRAFT_API && params.DO_TEST_DISTCHECK ) } }
|
||||
steps {
|
||||
dir("tmp/test-distcheck-withDRAFT") {
|
||||
deleteDir()
|
||||
unstash 'built-draft'
|
||||
script {
|
||||
def RETRY_NUMBER = 0
|
||||
retry(3) {
|
||||
RETRY_NUMBER++
|
||||
timeout (time: "${params.USE_TEST_TIMEOUT}".toInteger(), unit: 'MINUTES') {
|
||||
try {
|
||||
sh 'CCACHE_BASEDIR="`pwd`" ; export CCACHE_BASEDIR; LD_LIBRARY_PATH="`pwd`/src/.libs:$LD_LIBRARY_PATH"; export LD_LIBRARY_PATH; DISTCHECK_CONFIGURE_FLAGS="--enable-drafts=yes --with-docs=no" ; export DISTCHECK_CONFIGURE_FLAGS; make DISTCHECK_CONFIGURE_FLAGS="$DISTCHECK_CONFIGURE_FLAGS" LD_LIBRARY_PATH="$LD_LIBRARY_PATH" distcheck'
|
||||
}
|
||||
catch (Exception e) {
|
||||
currentBuild.result = 'UNSTABLE' // Jenkins should not let the verdict "improve"
|
||||
sh """D="`pwd`"; B="`basename "\$D"`" ; [ "${RETRY_NUMBER}" -gt 0 ] && T="_try-${RETRY_NUMBER}" || T="" ; tar czf "test-suite_${BUILD_TAG}_\${B}\${T}.tar.gz" `find . -name '*.trs'` `find . -name '*.log'`"""
|
||||
archiveArtifacts artifacts: "**/test-suite*.tar.gz", allowEmpty: true
|
||||
throw e
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
sh 'echo "Are GitIgnores good after make distcheck with drafts? (should have no output below)"; git status -s || if [ "${params.REQUIRE_GOOD_GITIGNORE}" = false ]; then echo "WARNING GitIgnore tests found newly changed or untracked files" >&2 ; exit 0 ; else echo "FAILED GitIgnore tests" >&2 ; exit 1; fi'
|
||||
script {
|
||||
if ( params.DO_CLEANUP_AFTER_BUILD ) {
|
||||
deleteDir()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage ('distcheck without DRAFT') {
|
||||
when { expression { return ( params.DO_BUILD_WITHOUT_DRAFT_API && params.DO_TEST_DISTCHECK ) } }
|
||||
steps {
|
||||
dir("tmp/test-distcheck-withoutDRAFT") {
|
||||
deleteDir()
|
||||
unstash 'built-nondraft'
|
||||
script {
|
||||
def RETRY_NUMBER = 0
|
||||
retry(3) {
|
||||
RETRY_NUMBER++
|
||||
timeout (time: "${params.USE_TEST_TIMEOUT}".toInteger(), unit: 'MINUTES') {
|
||||
try {
|
||||
sh 'CCACHE_BASEDIR="`pwd`" ; export CCACHE_BASEDIR; LD_LIBRARY_PATH="`pwd`/src/.libs:$LD_LIBRARY_PATH"; export LD_LIBRARY_PATH; DISTCHECK_CONFIGURE_FLAGS="--enable-drafts=no --with-docs=no" ; export DISTCHECK_CONFIGURE_FLAGS; make DISTCHECK_CONFIGURE_FLAGS="$DISTCHECK_CONFIGURE_FLAGS" LD_LIBRARY_PATH="$LD_LIBRARY_PATH" distcheck'
|
||||
}
|
||||
catch (Exception e) {
|
||||
currentBuild.result = 'UNSTABLE' // Jenkins should not let the verdict "improve"
|
||||
sh """D="`pwd`"; B="`basename "\$D"`" ; [ "${RETRY_NUMBER}" -gt 0 ] && T="_try-${RETRY_NUMBER}" || T="" ; tar czf "test-suite_${BUILD_TAG}_\${B}\${T}.tar.gz" `find . -name '*.trs'` `find . -name '*.log'`"""
|
||||
archiveArtifacts artifacts: "**/test-suite*.tar.gz", allowEmpty: true
|
||||
throw e
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
sh 'echo "Are GitIgnores good after make distcheck without drafts? (should have no output below)"; git status -s || if [ "${params.REQUIRE_GOOD_GITIGNORE}" = false ]; then echo "WARNING GitIgnore tests found newly changed or untracked files" >&2 ; exit 0 ; else echo "FAILED GitIgnore tests" >&2 ; exit 1; fi'
|
||||
script {
|
||||
if ( params.DO_CLEANUP_AFTER_BUILD ) {
|
||||
deleteDir()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage ('install with DRAFT') {
|
||||
when { expression { return ( params.DO_BUILD_WITH_DRAFT_API && params.DO_TEST_INSTALL ) } }
|
||||
steps {
|
||||
dir("tmp/test-install-withDRAFT") {
|
||||
deleteDir()
|
||||
unstash 'built-draft'
|
||||
retry(3) {
|
||||
timeout (time: "${params.USE_TEST_TIMEOUT}".toInteger(), unit: 'MINUTES') {
|
||||
sh """CCACHE_BASEDIR="`pwd`" ; export CCACHE_BASEDIR; LD_LIBRARY_PATH="`pwd`/src/.libs:\${LD_LIBRARY_PATH}"; export LD_LIBRARY_PATH; make LD_LIBRARY_PATH="\${LD_LIBRARY_PATH}" DESTDIR="${params.USE_TEST_INSTALL_DESTDIR}/withDRAFT" install"""
|
||||
}
|
||||
}
|
||||
sh """cd "${params.USE_TEST_INSTALL_DESTDIR}/withDRAFT" && find . -ls"""
|
||||
sh 'echo "Are GitIgnores good after make install with drafts? (should have no output below)"; git status -s || if [ "${params.REQUIRE_GOOD_GITIGNORE}" = false ]; then echo "WARNING GitIgnore tests found newly changed or untracked files" >&2 ; exit 0 ; else echo "FAILED GitIgnore tests" >&2 ; exit 1; fi'
|
||||
script {
|
||||
if ( params.DO_CLEANUP_AFTER_BUILD ) {
|
||||
deleteDir()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage ('install without DRAFT') {
|
||||
when { expression { return ( params.DO_BUILD_WITHOUT_DRAFT_API && params.DO_TEST_INSTALL ) } }
|
||||
steps {
|
||||
dir("tmp/test-install-withoutDRAFT") {
|
||||
deleteDir()
|
||||
unstash 'built-nondraft'
|
||||
retry(3) {
|
||||
timeout (time: "${params.USE_TEST_TIMEOUT}".toInteger(), unit: 'MINUTES') {
|
||||
sh """CCACHE_BASEDIR="`pwd`" ; export CCACHE_BASEDIR; LD_LIBRARY_PATH="`pwd`/src/.libs:\${LD_LIBRARY_PATH}"; export LD_LIBRARY_PATH; make LD_LIBRARY_PATH="\${LD_LIBRARY_PATH}" DESTDIR="${params.USE_TEST_INSTALL_DESTDIR}/withoutDRAFT" install"""
|
||||
}
|
||||
}
|
||||
sh """cd "${params.USE_TEST_INSTALL_DESTDIR}/withoutDRAFT" && find . -ls"""
|
||||
sh 'echo "Are GitIgnores good after make install without drafts? (should have no output below)"; git status -s || if [ "${params.REQUIRE_GOOD_GITIGNORE}" = false ]; then echo "WARNING GitIgnore tests found newly changed or untracked files" >&2 ; exit 0 ; else echo "FAILED GitIgnore tests" >&2 ; exit 1; fi'
|
||||
script {
|
||||
if ( params.DO_CLEANUP_AFTER_BUILD ) {
|
||||
deleteDir()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage ('install with DOCS') {
|
||||
when { expression { return ( params.DO_BUILD_DOCS && params.DO_TEST_INSTALL ) } }
|
||||
steps {
|
||||
dir("tmp/test-install-withDOCS") {
|
||||
deleteDir()
|
||||
unstash 'built-docs'
|
||||
retry(3) {
|
||||
timeout (time: "${params.USE_TEST_TIMEOUT}".toInteger(), unit: 'MINUTES') {
|
||||
sh """CCACHE_BASEDIR="`pwd`" ; export CCACHE_BASEDIR; LD_LIBRARY_PATH="`pwd`/src/.libs:\${LD_LIBRARY_PATH}"; export LD_LIBRARY_PATH; make LD_LIBRARY_PATH="\${LD_LIBRARY_PATH}" DESTDIR="${params.USE_TEST_INSTALL_DESTDIR}/withDOCS" install"""
|
||||
}
|
||||
}
|
||||
sh """cd "${params.USE_TEST_INSTALL_DESTDIR}/withDOCS" && find . -ls"""
|
||||
sh 'echo "Are GitIgnores good after make install with Docs? (should have no output below)"; git status -s || if [ "${params.REQUIRE_GOOD_GITIGNORE}" = false ]; then echo "WARNING GitIgnore tests found newly changed or untracked files" >&2 ; exit 0 ; else echo "FAILED GitIgnore tests" >&2 ; exit 1; fi'
|
||||
script {
|
||||
if ( params.DO_CLEANUP_AFTER_BUILD ) {
|
||||
deleteDir()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage ('deploy if appropriate') {
|
||||
steps {
|
||||
script {
|
||||
def myDEPLOY_JOB_NAME = sh(returnStdout: true, script: """echo "${params["DEPLOY_JOB_NAME"]}" """).trim();
|
||||
def myDEPLOY_BRANCH_PATTERN = sh(returnStdout: true, script: """echo "${params["DEPLOY_BRANCH_PATTERN"]}" """).trim();
|
||||
def myDEPLOY_REPORT_RESULT = sh(returnStdout: true, script: """echo "${params["DEPLOY_REPORT_RESULT"]}" """).trim().toBoolean();
|
||||
echo "Original: DEPLOY_JOB_NAME : ${params["DEPLOY_JOB_NAME"]} DEPLOY_BRANCH_PATTERN : ${params["DEPLOY_BRANCH_PATTERN"]} DEPLOY_REPORT_RESULT : ${params["DEPLOY_REPORT_RESULT"]}"
|
||||
echo "Used: myDEPLOY_JOB_NAME:${myDEPLOY_JOB_NAME} myDEPLOY_BRANCH_PATTERN:${myDEPLOY_BRANCH_PATTERN} myDEPLOY_REPORT_RESULT:${myDEPLOY_REPORT_RESULT}"
|
||||
if ( (myDEPLOY_JOB_NAME != "") && (myDEPLOY_BRANCH_PATTERN != "") ) {
|
||||
if ( env.BRANCH_NAME =~ myDEPLOY_BRANCH_PATTERN ) {
|
||||
def GIT_URL = sh(returnStdout: true, script: """git remote -v | egrep '^origin' | awk '{print \$2}' | head -1""").trim()
|
||||
def GIT_COMMIT = sh(returnStdout: true, script: 'git rev-parse --verify HEAD').trim()
|
||||
def DIST_ARCHIVE = ""
|
||||
if ( params.DO_DIST_DOCS ) { DIST_ARCHIVE = env.BUILD_URL + "artifact/__dist.tar.gz" }
|
||||
build job: "${myDEPLOY_JOB_NAME}", parameters: [
|
||||
string(name: 'DEPLOY_GIT_URL', value: "${GIT_URL}"),
|
||||
string(name: 'DEPLOY_GIT_BRANCH', value: env.BRANCH_NAME),
|
||||
string(name: 'DEPLOY_GIT_COMMIT', value: "${GIT_COMMIT}"),
|
||||
string(name: 'DEPLOY_DIST_ARCHIVE', value: "${DIST_ARCHIVE}")
|
||||
], quietPeriod: 0, wait: myDEPLOY_REPORT_RESULT, propagate: myDEPLOY_REPORT_RESULT
|
||||
} else {
|
||||
echo "Not deploying because branch '${env.BRANCH_NAME}' did not match filter '${myDEPLOY_BRANCH_PATTERN}'"
|
||||
}
|
||||
} else {
|
||||
echo "Not deploying because deploy-job parameters are not set"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
post {
|
||||
success {
|
||||
script {
|
||||
if (currentBuild.getPreviousBuild()?.result != 'SUCCESS') {
|
||||
// Uncomment desired notification
|
||||
|
||||
//slackSend (color: "#008800", message: "Build ${env.JOB_NAME} is back to normal.")
|
||||
//emailext (to: "qa@example.com", subject: "Build ${env.JOB_NAME} is back to normal.", body: "Build ${env.JOB_NAME} is back to normal.")
|
||||
}
|
||||
}
|
||||
}
|
||||
failure {
|
||||
// Uncomment desired notification
|
||||
// Section must not be empty, you can delete the sleep once you set notification
|
||||
sleep 1
|
||||
//slackSend (color: "#AA0000", message: "Build ${env.BUILD_NUMBER} of ${env.JOB_NAME} ${currentBuild.result} (<${env.BUILD_URL}|Open>)")
|
||||
//emailext (to: "qa@example.com", subject: "Build ${env.JOB_NAME} failed!", body: "Build ${env.BUILD_NUMBER} of ${env.JOB_NAME} ${currentBuild.result}\nSee ${env.BUILD_URL}")
|
||||
}
|
||||
}
|
||||
}
|
||||
2208
3rd/libzmq/NEWS
Normal file
2208
3rd/libzmq/NEWS
Normal file
@@ -0,0 +1,2208 @@
|
||||
0MQ version 4.3.4 stable, released on 2020/01/17
|
||||
================================================
|
||||
|
||||
* New DRAFT (see NEWS for 4.2.0) socket option:
|
||||
- ZMQ_PRIORITY will set the SO_PRIORITY socket option on the underlying
|
||||
sockets. Only supported on Linux.
|
||||
See doc/zmq_setsockopt.txt and doc/zmq_getsockopt.txt for details.
|
||||
|
||||
* Fixed #4113 - compilation errors on kFreeBSD and GNU/Hurd
|
||||
|
||||
* Fixed #4086 - excessive amount of socket files left behind in Windows TMP
|
||||
directory
|
||||
|
||||
* Fixed #4108 - regression that breaks using IPv6 link-local addresses on Linux
|
||||
|
||||
* Fixed #4078 - compilation errors on Android
|
||||
|
||||
* Fixed #4074 - compilation error with ulibc and libbsd
|
||||
|
||||
* Fixed #4060 - stack overflow on Windows x64
|
||||
|
||||
* Fixed #4051 - various compilation errors on Windows ARM 32bit
|
||||
|
||||
* Fixed #4043 - various compilation warnings with XCode
|
||||
|
||||
* Fixed #4038 - return value of zmq_ctx_get changed unintentionally
|
||||
|
||||
|
||||
0MQ version 4.3.3 stable, released on 2020/09/07
|
||||
================================================
|
||||
|
||||
* Security advisories:
|
||||
* CVE-2020-15166: Denial-of-Service on CURVE/ZAP-protected servers by
|
||||
unauthenticated clients.
|
||||
If a raw TCP socket is opened and connected to an endpoint that is fully
|
||||
configured with CURVE/ZAP, legitimate clients will not be able to exchange
|
||||
any message. Handshakes complete successfully, and messages are delivered to
|
||||
the library, but the server application never receives them.
|
||||
For more information see the security advisory:
|
||||
https://github.com/zeromq/libzmq/security/advisories/GHSA-25wp-cf8g-938m
|
||||
* Stack overflow on server running PUB/XPUB socket (CURVE disabled).
|
||||
The PUB/XPUB subscription store (mtrie) is traversed using recursive
|
||||
function calls. In the remove (unsubscription) case, the recursive calls are
|
||||
NOT tail calls, so even with optimizations the stack grows linearly with the
|
||||
length of a subscription topic. Topics are under the control of remote
|
||||
clients - they can send a subscription to arbitrary length topics. An
|
||||
attacker can thus cause a server to create an mtrie sufficiently large such
|
||||
that, when unsubscribing, traversal will cause a stack overflow.
|
||||
For more information see the security advisory:
|
||||
https://github.com/zeromq/libzmq/security/advisories/GHSA-qq65-x72m-9wr8
|
||||
* Memory leak in PUB server induced by malicious client(s) without CURVE/ZAP.
|
||||
Messages with metadata are never processed by PUB sockets, but the metadata
|
||||
is kept referenced in the PUB object and never freed.
|
||||
For more information see the security advisory:
|
||||
https://github.com/zeromq/libzmq/security/advisories/GHSA-4p5v-h92w-6wxw
|
||||
* Memory leak in client induced by malicious server(s) without CURVE/ZAP.
|
||||
When a pipe processes a delimiter and is already not in active state but
|
||||
still has an unfinished message, the message is leaked.
|
||||
For more information see the security advisory:
|
||||
https://github.com/zeromq/libzmq/security/advisories/GHSA-wfr2-29gj-5w87
|
||||
* Heap overflow when receiving malformed ZMTP v1 packets (CURVE disabled).
|
||||
By crafting a packet which is not valid ZMTP v2/v3, and which has two
|
||||
messages larger than 8192 bytes, the decoder can be tricked into changing
|
||||
the recorded size of the 8192 bytes static buffer, which then gets overflown
|
||||
by the next message. The content that gets written in the overflown memory
|
||||
is entirely decided by the sender.
|
||||
For more information see the security advisory:
|
||||
https://github.com/zeromq/libzmq/security/advisories/GHSA-fc3w-qxf5-7hp6
|
||||
|
||||
* Note for packagers: an external, self-contained sha1 library is now
|
||||
included in the source tree under external/sha1/ - it is licensed
|
||||
under BSD-3-Clause and thus it is fully compatible with libzmq's
|
||||
license.
|
||||
It is only used if WebSockets support is enabled, and if neither GnuTLS nor
|
||||
NSS are available.
|
||||
|
||||
* Note for packagers: an internal reimplementation of strlcpy is now included,
|
||||
for wider platform compatibility.
|
||||
libbsd can be used and is enabled by default if available instead of the
|
||||
internal implementation, for better security maintenance in distros.
|
||||
|
||||
* Note for packagers: ZeroMQConfig.cmake is now installed in the arch-dependent
|
||||
subdirectory - eg: /usr/lib/x86_64-linux-gnu/cmake/
|
||||
|
||||
* New DRAFT (see NEWS for 4.2.0) socket type:
|
||||
- ZMQ_CHANNEL is a thread-safe alternative to ZMQ_PAIR.
|
||||
See doc/zmq_socket.txt for details.
|
||||
|
||||
* New DRAFT (see NEWS for 4.2.0) socket option:
|
||||
- ZMQ_ONLY_FIRST_SUBSCRIBE will cause only the first part of a multipart
|
||||
message to be processed as a subscribe/unsubscribe message, and the rest
|
||||
will be forwarded as user data to the application.
|
||||
- ZMQ_RECONNECT_STOP will cause a connecting socket to stop trying to
|
||||
reconnect in specific circumstances. See the manpage for details.
|
||||
- ZMQ_HELLO_MSG to set a message that will be automatically sent to a new
|
||||
connection.
|
||||
- ZMQ_DISCONNECT_MSG to set a message that will be automatically received when
|
||||
a peer disconnects.
|
||||
See doc/zmq_setsockopt.txt and doc/zmq_getsockopt.txt for details.
|
||||
|
||||
* New DRAFT (see NEWS for 4.2.0) zmq_ctx_get_ext/zmq_ctx_set_ext APIs were added
|
||||
to allow enhancing the context options with variable data inputs.
|
||||
See doc/zmq_ctx_get_ext.txt and doc/zmq_ctx_set_ext.txt for details.
|
||||
|
||||
* New DRAFT (see NEWS for 4.2.0) transport options WS and WSS added for support
|
||||
of WebSockets (and secure WebSockets via TLS) via the ZWS 2.0 protocol.
|
||||
WSS requires the GnuTLS library for TLS support. ZMQ_WSS_ specific socket
|
||||
options were added to support TLS.
|
||||
WebSockets support is disabled by default if DRAFT APIs are disabled.
|
||||
|
||||
* New DRAFT (see NEWS for 4.2.0) socket type, PEER, which is thread safe and a
|
||||
related zmq_connect_peer function which atomically and thread-safely connects
|
||||
and returns a routing-id.
|
||||
|
||||
* New DRAFT (see NEWS for 4.2.0) zmq_msg_init_buffer API was added to allow
|
||||
the construction of a message by copying from an existing buffer.
|
||||
|
||||
* New DRAFT (see NEWS for 4.2.0) zmq_poller_size API was added to allow querying
|
||||
the number of sockets/fds registered in a zmq_poller.
|
||||
|
||||
* ZMTP 3.1 peers will receive subscribe/cancel on PUB/SUB via commands rather
|
||||
than using the first byte of the payload.
|
||||
|
||||
* zmq_z85_decode now checks that the input string's length is at least 5 characters
|
||||
and always a multiple of 5 as per API specification.
|
||||
|
||||
* Fixed #3566 - malformed CURVE message can cause memory leak
|
||||
|
||||
* Fixed #3567 - missing ZeroMQ_INCLUDE_DIR in ZeroMQConfig.cmake when only
|
||||
static lib is built
|
||||
|
||||
* Fixed #3576 - CURVE plaintext secrets now stored in libsodium's secure memory
|
||||
|
||||
* Fixed #3588 - install debug libraries for debug msvc builds with CMake
|
||||
|
||||
* Fixed #3591 - incorrect ZMQ_MAX_SOCKETS default value in doc
|
||||
|
||||
* Fixed #3594 - fixed stream_engine use after free due to concurrent heartbeats
|
||||
|
||||
* Fixed #3586 - error when compiling with MinGW due to usage of MS-specific
|
||||
__except keyword
|
||||
|
||||
* Fixed #3603 - fixed CMake build on SL6.9
|
||||
|
||||
* Fixed #3607 - added scripts to ease performance graph generation
|
||||
|
||||
* Fixed #3608 - fix for IPv4 mapping not supported in DragonFlyBSD
|
||||
|
||||
* Fixed #3636 - added ENABLE_PRECOMPILED CMake option to fix build with Ninja
|
||||
|
||||
* Fixed #2862 - UDP engine aborts on networking-related errors from socket
|
||||
syscalls
|
||||
|
||||
* Fixed #3656 - segfault on sending data from XSUB to XPUB
|
||||
|
||||
* Fixed #3646 - static-only test run fails
|
||||
|
||||
* Fixed #3668 - fixed CMAKE_CXX_FLAGS_* regexes on MSVC
|
||||
|
||||
* Fixed #110 - do not include winsock2.h in public zmq.h header
|
||||
|
||||
* Fixed #3683 - allow "configure --disable-maintainer-mode"
|
||||
|
||||
* Fixed #3686 - fix documentation about sockets blocking on send operations
|
||||
|
||||
* Fixed #3323 - fix behavior of ZMQ_CONFLATE on PUB sockets
|
||||
|
||||
* Fixed #3698 - fix build on IBM i/PASE/os400
|
||||
|
||||
* Fixed #3705 - zero-sized messages cause assertion when glibc assertion are on
|
||||
|
||||
* Fixed #3713 - remove dependency on math library by avoiding std::ceil
|
||||
|
||||
* Fixed #3694 - build targeting Windows XP is broken
|
||||
|
||||
* Fixed #3691 - added support for IPC on Windows 10 via AF_UNIX
|
||||
|
||||
* Fixed #3725 - disable by default test that requires sudo on CMake
|
||||
|
||||
* Fixed #3727 - fix zmq_poller documentation example
|
||||
|
||||
* Fixed #3729 - do not check for FD_OOB when using WSAEventSelect on Windows
|
||||
|
||||
* Fixed #3738 - allow renaming the library in CMake
|
||||
|
||||
* Fixed #1808 - use AF_UNIX instead of TCP for the internal socket on Windows 10
|
||||
|
||||
* Fixed #3758 - fix pthread_set_affinity detection in CMake
|
||||
|
||||
* Fixed #3769 - fix undefined behaviour in array.hpp
|
||||
|
||||
* Fixed #3772 - fix compiling under msys2-mingw
|
||||
|
||||
* Fixed #3775 - add -latomic to the private libs flag in pkg-config if needed
|
||||
|
||||
* Fixed #3778 - fix documentation of zmq_poller's thread safety
|
||||
|
||||
* Fixed #3792 - do not allow creation of new sockets after zmq_ctx_shutdown
|
||||
|
||||
* Fixed #3805 - improve performance of CURVE by reducing copies
|
||||
|
||||
* Fixed #3814 - send subscribe/cancel as commands to ZMTP 3.1 peers
|
||||
|
||||
* Fixed #3847 - fix building without PGM and NORM
|
||||
|
||||
* Fixed #3849 - install .cmake file in arch-dependent subdirectory
|
||||
|
||||
* Fixed #4005 - allow building on Windows ARM/ARM64
|
||||
|
||||
0MQ version 4.3.2 stable, released on 2019/07/08
|
||||
================================================
|
||||
|
||||
* CVE-2019-13132: a remote, unauthenticated client connecting to a
|
||||
libzmq application, running with a socket listening with CURVE
|
||||
encryption/authentication enabled, may cause a stack overflow and
|
||||
overwrite the stack with arbitrary data, due to a buffer overflow in
|
||||
the library. Users running public servers with the above configuration
|
||||
are highly encouraged to upgrade as soon as possible, as there are no
|
||||
known mitigations. All versions from 4.0.0 and upwards are affected.
|
||||
Thank you Fang-Pen Lin for finding the issue and reporting it!
|
||||
|
||||
* New DRAFT (see NEWS for 4.2.0) zmq_socket_monitor_versioned API that supports
|
||||
a versioned monitoring events protocol as a parameter. Passing 1 results in
|
||||
the same behaviour as zmq_socket_monitor.
|
||||
Version 2 of the events protocol allows new events, new metadata, different
|
||||
socket types for the monitors and more. It is described in details in
|
||||
doc/zmq_socket_monitor_versioned.txt
|
||||
|
||||
* New DRAFT (see NEWS for 4.2.0) zmq_socket_monitor_pipes_stats that triggers
|
||||
a new ZMQ_EVENT_PIPES_STATS to be delivered via zmq_socket_monitor_versioned
|
||||
v2 API, which contains the current status of all the queues owned by the
|
||||
monitored socket. See doc/zmq_socket_monitor_versioned.txt for details.
|
||||
|
||||
* New DRAFT (see NEWS for 4.2.0) zmq_poller_fd that returns the FD of a thread
|
||||
safe socket. See doc/zmq_poller.txt for details.
|
||||
|
||||
* New DRAFT (see NEWS for 4.2.0) socket options:
|
||||
- ZMQ_XPUB_MANUAL_LAST_VALUE is similar to ZMQ_XPUB_MANUAL but allows to avoid
|
||||
duplicates when using last value caching.
|
||||
- ZMQ_SOCKS_USERNAME and ZMQ_SOCKS_PASSWORD that implement SOCKS5 proxy
|
||||
authentication.
|
||||
See doc/zmq_setsockopt.txt and doc/zmq_getsockopt.txt for details.
|
||||
|
||||
* Implemented background thread names for Windows, when the Visual Studio
|
||||
debugger is being used.
|
||||
|
||||
* Fixed #3358 - test_security_zap failing due to SIGBUS on SPARC64, hard-coded
|
||||
IPC socket binds in tests cause race conditions
|
||||
|
||||
* Fixed #3361 - enabling GSSAPI support (when using autools) does not work due
|
||||
to regression introduced in 4.2.3
|
||||
|
||||
* Fixed #3362 - remove documentation for ZMQ_THREAD_PRIORITY context option
|
||||
getter, it's not implemented
|
||||
|
||||
* Fixed #3363 - tests fail to build due to stricter compiler printf validation
|
||||
in new versions of GCC
|
||||
|
||||
* Fixed #3367 - try to infer cacheline size at build time, first with
|
||||
getconf LEVEL1_DCACHE_LINESIZE, and then by reading
|
||||
/sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size
|
||||
(autoconf only), and only then falling back to the previous
|
||||
default of 64 bytes. Avoids false sharing on POWER and s390x.
|
||||
Import ax_func_posix_memalign.m4 as a more reliable check for
|
||||
posix_memalign presence on some unix platforms.
|
||||
Prefer c++11 atomic primitives to compiler intrinsics, when
|
||||
both are available, as the former is more reliable.
|
||||
Set test_pair_ipc and test_rebind_ipc to XFAIL on GNU/Hurd due
|
||||
to non-functioning getsockname on AF_UNIX.
|
||||
|
||||
* Fixed #3370 - Make queue length and HWM state observable
|
||||
|
||||
* Fixed #3373 - performance regression in zmq_poll on CentOS 6/7
|
||||
|
||||
* Fixed #3375 - assign names to all pthreads created by the library to ease
|
||||
debugging
|
||||
|
||||
* Fixed #3376 - assigned random TIPC port is not returned by ZMQ_LAST_ENDPOINT
|
||||
|
||||
* Fixed #3385 - TCP port in ZMQ_LAST_ENDPOINT depends on global locale
|
||||
|
||||
* Fixed #3404 - use std::condition_variable_any when possible
|
||||
|
||||
* Fixed #3436 - reconnect interval exponential backoff and may lead to integer
|
||||
overflows
|
||||
|
||||
* Fixed #3440 - improve zmq_proxy performance by batching of up to 1000
|
||||
consecutive messages (if any) and add perf/proxy_thr tool
|
||||
|
||||
* Fixed #3451 - fix support of /dev/poll on Solaris
|
||||
|
||||
* Fixed #3452 - strnlen may not be available
|
||||
|
||||
* Fixed #1462 - test failure in test_filter_ipc due to invalid system groups
|
||||
|
||||
* Fixed #3269 - Boost.ASIO integration stopped working with v4.3.0
|
||||
|
||||
* Fixed #3479 - ZeroMQ does not build for QNX 6.6 with CMake
|
||||
|
||||
* Fixed #3481 - add <ios> include to fix uClibc++ compilation
|
||||
|
||||
* Fixed #3491 - build broken on Fedora 30
|
||||
|
||||
* Fixed #3494 - ZeroMQConfig.cmake fails if shared libraries are not built
|
||||
|
||||
* Fixed #3498 - syntax error on Windows related to socket descriptor type
|
||||
|
||||
* Fixed #3500 - PLAIN HELLO message incorrectly uses WELCOME literal, regression
|
||||
introduced in 4.3.0
|
||||
|
||||
* Fixed #3517 - configure errors because of syntax errors in the use of test
|
||||
shell command
|
||||
|
||||
* Fixed #3521 - document how to achieve high performance with the PGM transport
|
||||
|
||||
* Fixed #3526 - failure case behavior unclear in zmq_msg_send documentation
|
||||
|
||||
* Fixed #3537 - fix build on z/OS by using pthread_equal instead of comparing
|
||||
variables directly
|
||||
|
||||
* Fixed #3546 - CMake links with librt on MinGW which is not available
|
||||
|
||||
* Many coding style, duplication, testing and static analysis improvements.
|
||||
|
||||
|
||||
0MQ version 4.3.1 stable, released on 2019/01/12
|
||||
================================================
|
||||
|
||||
* CVE-2019-6250: A vulnerability has been found that would allow attackers to
|
||||
direct a peer to jump to and execute from an address indicated by the
|
||||
attacker.
|
||||
This issue has been present since v4.2.0. Older releases are not affected.
|
||||
NOTE: The attacker needs to know in advance valid addresses in the peer's
|
||||
memory to jump to, so measures like ASLR are effective mitigations.
|
||||
NOTE: this attack can only take place after authentication, so peers behind
|
||||
CURVE/GSSAPI are not vulnerable to unauthenticated attackers.
|
||||
See https://github.com/zeromq/libzmq/issues/3351 for more details.
|
||||
Thanks to Guido Vranken for uncovering the issue and providing the fix!
|
||||
|
||||
* Note for packagers: as pkg-config's Requires.private is now used to properly
|
||||
propagate dependencies for static builds, the libzmq*-dev or zeromq-devel or
|
||||
equivalent package should now depend on the libfoo-dev or foo-devel packages
|
||||
of all the libraries that zmq is linked against, or pkg-config --libs libzmq
|
||||
will fail due to missing dependencies on end users machines.
|
||||
|
||||
* Fixed #3351 - remote code execution vulnerability.
|
||||
|
||||
* Fixed #3343 - race condition in ZMQ_PUSH when quickly disconnecting and
|
||||
reconnecting causes last part of multi-part message to get
|
||||
"stuck" and resent by mistake to the new socket.
|
||||
|
||||
* Fixed #3336 - set Requires.private in generate pkg-config file.
|
||||
|
||||
* Fixed #3334 - set TCP_NODELAY after connect() on Windows for the I/O socket.
|
||||
|
||||
* Fixed #3326 - assert on Android when opening a socket and disabling WiFi.
|
||||
|
||||
* Fixed #3320 - build failure on OpenBSD with GCC.
|
||||
|
||||
0MQ version 4.3.0 stable, released on 2018/11/28
|
||||
================================================
|
||||
|
||||
* The following DRAFT APIs have been marked as STABLE and will not change
|
||||
anymore:
|
||||
- ZMQ_MSG_T_SIZE context option (see doc/zmq_ctx_get.txt)
|
||||
- ZMQ_THREAD_AFFINITY_CPU_ADD and ZMQ_THREAD_AFFINITY_CPU_REMOVE (Posix only)
|
||||
context options, to add/remove CPUs to the affinity set of the I/O threads.
|
||||
See doc/zmq_ctx_set.txt and doc/zmq_ctx_get.txt for details.
|
||||
- ZMQ_THREAD_NAME_PREFIX (Posix only) context option, to add a specific
|
||||
integer prefix to the background threads names, to easily identify them.
|
||||
See doc/zmq_ctx_set.txt and doc/zmq_ctx_get.txt for details.
|
||||
- ZMQ_GSSAPI_PRINCIPAL_NAMETYPE and ZMQ_GSSAPI_SERVICE_PRINCIPAL_NAMETYPE
|
||||
socket options, for the corresponding GSSAPI features. Additional
|
||||
definitions for principal name types:
|
||||
- ZMQ_GSSAPI_NT_HOSTBASED
|
||||
- ZMQ_GSSAPI_NT_USER_NAME
|
||||
- ZMQ_GSSAPI_NT_KRB5_PRINCIPAL
|
||||
See doc/zmq_gssapi.txt for details.
|
||||
- ZMQ_BINDTODEVICE socket option (Linux only), which will bind the
|
||||
socket(s) to the specified interface. Allows to use Linux VRF, see:
|
||||
https://www.kernel.org/doc/Documentation/networking/vrf.txt
|
||||
NOTE: requires the program to be ran as root OR with CAP_NET_RAW
|
||||
- zmq_timers_* APIs. These functions can be used for cross-platforms timed
|
||||
callbacks. See doc/zmq_timers.txt for details.
|
||||
- The following socket monitor events:
|
||||
- ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL: unknown errors during handshake.
|
||||
- ZMQ_EVENT_HANDSHAKE_SUCCEEDED: Handshake completed with authentication.
|
||||
- ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL: Protocol errors with peers or ZAP.
|
||||
- ZMQ_EVENT_HANDSHAKE_FAILED_AUTH: Failed authentication requests.
|
||||
See doc/zmq_socket_monitor.txt for more details and error codes.
|
||||
- zmq_stopwatch_intermediate which returns the time elapsed without stopping
|
||||
the stopwatch.
|
||||
- zmq_proxy_steerable command 'STATISTICS' to retrieve stats about the amount
|
||||
of messages and bytes sent and received by the proxy.
|
||||
See doc/zmq_proxy_steerable.txt for more information.
|
||||
|
||||
* The build-time configuration option to select the poller has been split, and
|
||||
new API_POLLER (CMake) and --with-api-poller (autoconf) options will now
|
||||
determine what system call is used to implement the zmq_poll/zmq_poller APIs.
|
||||
The previous POLLER and --with-poller options now only affects the
|
||||
internal I/O thread. In case API_POLLER is not specified, the behaviour keeps
|
||||
backward compatibility intact and will be the same as with previous releases.
|
||||
|
||||
* The non-default "poll" poller for the internal I/O thread (note: NOT for the
|
||||
zmq_poll/zmq_poller user APIs!) has been disabled on Windows as WSAPoll does
|
||||
not report connection failures. For more information see:
|
||||
- https://daniel.haxx.se/blog/2012/10/10/wsapoll-is-broken/
|
||||
- https://curl.haxx.se/mail/lib-2012-10/0038.html
|
||||
- https://bugs.python.org/issue16507
|
||||
|
||||
* New epoll implementation for Windows, using the following implementation:
|
||||
https://github.com/piscisaureus/wepoll/tree/v1.5.4
|
||||
To use this, select "epoll" as the poller option in the build system.
|
||||
Note for distributors: the wepoll source code is embedded and distributed.
|
||||
It is licensed under the BSD-2-Clause and thus it is compatible with LGPL-3.0.
|
||||
Note that, if selected at build time, the license text must be distributed
|
||||
with the binary in accordance to the license terms. A copy can be found at:
|
||||
external/wepoll/license.txt
|
||||
|
||||
* The pre-made Visual Studio solutions file are deprecated, and users are
|
||||
encouraged to use the CMake solution generation feature instead.
|
||||
|
||||
* New DRAFT (see NEWS for 4.2.0) socket options:
|
||||
- ZMQ_ROUTER_NOTIFY to deliver a notification when a peer connects and/or
|
||||
disconnects in the form of a routing id plus a zero-length frame.
|
||||
- ZMQ_MULTICAST_LOOP to control whether the data sent should be looped back
|
||||
on local listening sockets for UDP multicast sockets (ZMQ_RADIO).
|
||||
See doc/zmq_setsockopt.txt and doc/zmq_getsockopt.txt for details.
|
||||
|
||||
* New perf tool, perf/benchmark_radix_tree, to measure the performance of the
|
||||
different internal implementations of the trie algorithm used to track
|
||||
subscriptions. Requires a compiler that supports C++11.
|
||||
|
||||
* New autoconf flag "--enable-force-CXX98-compat" which will force -std=gnu++98
|
||||
and, if the compiler supports them (clang++ at the moment), it will also add
|
||||
-Wc++98-compat -Wc++98-compat-pedantic so that compatibility with C++98 can
|
||||
be tested.
|
||||
|
||||
* Many, many coding style, duplication and static analysis improvements.
|
||||
|
||||
* Many, many improvements to the CMake build system, especially on Windows.
|
||||
|
||||
* Many, many improvements to unit tests.
|
||||
|
||||
* Fixed #3036 - Compilation error when -pedantic is used.
|
||||
|
||||
* Fixed #3028 - Failure when zmq_poller_destroy is called after zmq_ctx_term.
|
||||
|
||||
* Fixed #2989 - CMake: Linker PDB install rule does not work when Visual Studio
|
||||
generators are used.
|
||||
|
||||
* Fixed #3045 - configure.ac: search for dladdr only when using libunwind.
|
||||
|
||||
* Fixed #3060 - REQ sockets terminate TCP connection after first heartbeat if
|
||||
ZMQ_HEARTBEAT_IVL is set.
|
||||
|
||||
* Fixed #2212 - UDP: need ability to specify bind address separately from
|
||||
multicast address for multi-homed hosts.
|
||||
|
||||
* Fixed #2891 - UDP: address name resolution is limited to dotted IPv4 rather
|
||||
than being capable of IPv4, IPv6, and hostname lookup.
|
||||
|
||||
* Fixed #3085 - autoconf/CMake getrandom test does not check if it's working but
|
||||
only for its presence.
|
||||
|
||||
* Fixed #3090 - compilation broken with Solaris Studio.
|
||||
|
||||
* Fixed #3094 - UDP: pass interface via IP[V6]_MULTICAST_IF if provided.
|
||||
|
||||
* Fixed #3061 - implement ZMTP 3.1 ping/pong context sending/receiving.
|
||||
|
||||
* Fixed #2188 - Added documentation for new zmq_poller API.
|
||||
|
||||
* Fixed #3088 - zmq_poller_add/zmq_poller_modify should reject invalid events
|
||||
arguments.
|
||||
|
||||
* Fixed #3042 - Fixed compilation on ARM with ZMQ_ATOMIC_PTR_MUTEX.
|
||||
|
||||
* Fixed #3107 - test_immediate_3/test_reconnect_inproc do not terminate with
|
||||
POLL as the I/O thread poller under Windows.
|
||||
|
||||
* Fixed #3046 - Aborts when iOS abuses EBADF to report a socket has been
|
||||
reclaimed.
|
||||
|
||||
* Fixed #3136 - Cannot set ZMQ_HEARTBEAT_TTL to more than 655.3 seconds.
|
||||
|
||||
* Fixed #3083 - link with -latomic when needed.
|
||||
|
||||
* Fixed #3162 - build failure with MUSL libc.
|
||||
|
||||
* Fixed #3158 - -1 value of ZMQ_RECONNECT_IVL was not correctly handled on some
|
||||
platforms.
|
||||
|
||||
* Fixed #3170 - improved documentation for ZMQ_PAIR.
|
||||
|
||||
* Fixed #3168 - correctly use symbols map on Debian/kFreeBSD and Debian/HURD
|
||||
to avoid exporting standard library symbols.
|
||||
|
||||
* Fixed #3168 - correctly process ZMTP 3.1 cancel/subscribe commands.
|
||||
|
||||
* Fixed #3171 - improve documentation for ZMQ_CONFLATE.
|
||||
|
||||
* Fixed #2876 - stack overflow on Windows 64.
|
||||
|
||||
* Fixed #3191 - race condition with received message causes
|
||||
ZMQ_CONNECT_ROUTING_ID to be assigned to wrong socket.
|
||||
|
||||
* Fixed #3005 - added documentation for new zmq_timers_* API.
|
||||
|
||||
* Fixed #3222 - use /Z7 debug on Release builds too on Windows (CMake).
|
||||
|
||||
* Fixed #3226 - possible PGM receiver crash.
|
||||
|
||||
* Fixed #3236 - UDP dish socket can't bind to a multicast port already in use.
|
||||
|
||||
* Fixed #3242 - improve HWM documentation.
|
||||
|
||||
* Fixed #2488 - improve zmq_msg_send doc return value documentation.
|
||||
|
||||
* Fixed #3268 - HWM in ZMQ_DGRAM socket does not respect multipart message.
|
||||
|
||||
* Fixed #3284 - added support for ZMQ_MULTICAST_HOPS with UDP sockets.
|
||||
|
||||
* Fixed #3245 - use-after-free reported in zmq::pipe_t::terminate.
|
||||
|
||||
* Fixed #1400 - use patricia trie for subscription to improve performances and
|
||||
memory usage. Note: only active in DRAFT builds for now.
|
||||
|
||||
* Fixed #3263 - fix abort on Windows when a large TCP read is requested and
|
||||
fails.
|
||||
|
||||
* Fixed #3312 - fix build on Android Things 1.06 with Termux.
|
||||
|
||||
|
||||
0MQ version 4.2.5 stable, released on 2018/03/23
|
||||
================================================
|
||||
|
||||
* Fixed #3018 - fix backward-incompatible change in the NULL auth
|
||||
mechanism that slipped in 4.2.3 and made connections
|
||||
with a ZAP domain set on a socket but without a working
|
||||
ZAP handler fail. See ZMQ_ZAP_ENFORCE_DOMAIN and RFC27.
|
||||
|
||||
* Fixed #3016 - clarify in zmq_close manpage that the operation will
|
||||
complete asynchronously.
|
||||
|
||||
* Fixed #3012 - fix CMake build problem when using LIBZMQ_WERROR and a
|
||||
compiler other than GCC.
|
||||
|
||||
|
||||
0MQ version 4.2.4 stable, released on 2018/03/21
|
||||
================================================
|
||||
|
||||
* New DRAFT (see NEWS for 4.2.0) socket options:
|
||||
- ZMQ_LOOPBACK_FASTPATH to enable faster TCP loopback on Windows
|
||||
- ZMQ_METADATA to set application-specific metadata on a socket
|
||||
See doc/zmq_setsockopt.txt and doc/zmq_getsockopt.txt for details.
|
||||
|
||||
* New DRAFT (see NEWS for 4.2.0) context options:
|
||||
- ZMQ_ZERO_COPY_RECV to disable zero-copy receive to save memory
|
||||
at the expense of slower performance
|
||||
See doc/zmq_ctx_set.txt and doc/zmq_ctx_get.txt for details.
|
||||
|
||||
* New DRAFT API zmq_stopwatch_intermediate which returns the time
|
||||
elapsed without stopping the stopwatch.
|
||||
|
||||
* TIPC: support addressing TIPC Port Identity addresses.
|
||||
|
||||
* Added CMake option to disable tests: BUILD_TESTS
|
||||
|
||||
* Added CMake and autotools make targets to support clang-formatter:
|
||||
make clang-format, clang-format-check and clang-format-diff to
|
||||
help developers make sure their code conforms to the style guidelines
|
||||
|
||||
* For distributors: a new test framework has been added, which
|
||||
includes a copy of the Unity source code. This source code library is
|
||||
distributed under the MIT license and thus is compatible with
|
||||
libzmq's LGPL3.
|
||||
|
||||
* Fixed #2867 - add ZeroMQConfig.cmake.in to distributable tarball
|
||||
|
||||
* Fixed #2868 - fix OpenBSD build
|
||||
|
||||
* Fixed #2870 - fix VC++ 11.0 (VS2012) build
|
||||
|
||||
* Fixed #2879 - prevent duplicate connections on PUB sockets
|
||||
|
||||
* Fixed #2872 - fix CMake tests on Windows
|
||||
|
||||
* Fixed #2895 - fix assert on Windows with POLL
|
||||
|
||||
* Fixed #2920 - fix Windows build with Intel compiler
|
||||
|
||||
* Fixed #2930 - use std::atomic when available with VC++ and VS2015
|
||||
|
||||
* Fixed #2910 - fix race condition with ZMQ_LINGER socket option
|
||||
|
||||
* Fixed #2927 - add support for ZMQ_XPUB_NODROP on ZMQ_RADIO
|
||||
|
||||
* Fixed #2820 - further clarify ZMQ_XPUB_VERBOSE(R) documentation.
|
||||
|
||||
* Fixed #2911 - ZMQ_DISH over UDP triggers errno_assert() after hitting
|
||||
watermark
|
||||
|
||||
* Fixed #2942 - ZMQ_PUB crash when due to high volume of subscribe and
|
||||
unsubscribe messages, an unmatched unsubscribe message is
|
||||
received in certain conditions
|
||||
|
||||
* Fixed #2946 - fix Windows CMake build when BUILD_SHARED is off
|
||||
|
||||
* Fixed #2960 - fix build with GCC 8
|
||||
|
||||
* Fixed #2967 - fix race condition on thread safe sockets due to pthread
|
||||
condvar timeouts on OSX
|
||||
|
||||
* Fixed #2977 - fix TIPC build-time availability check to be more relaxed
|
||||
|
||||
* Fixed #2966 - add support for WindRiver VxWorks 6.x
|
||||
|
||||
* Fixed #2963 - fix some PVS Studio static analysis warnings
|
||||
|
||||
* Fixed #2983 - fix MinGW cross-compilation
|
||||
|
||||
* Fixed #2991 - fix mutex assert at shutdown when the zmq context is part
|
||||
of a class declared as a global static
|
||||
|
||||
|
||||
0MQ version 4.2.3 stable, released on 2017/12/13
|
||||
================================================
|
||||
|
||||
* API change: previously ZMQ_POLLOUT on a ZMQ_ROUTER socket returned always
|
||||
true due to how the type works. When ZMQ_ROUTER_MANDATORY is set, sending
|
||||
fails when the peer is not available, but ZMQ_POLLOUT always returns true
|
||||
anyway, which does not make sense. Now when ZMQ_ROUTER_MANDATORY is set,
|
||||
ZMQ_POLLOUT on a ZMQ_ROUTER will return true only if at least one peer is
|
||||
available.
|
||||
Given ZMQ_POLLOUT with ZMQ_ROUTER was not usable at all previously, we do
|
||||
not consider this a breakage warranting a major or minor version increase.
|
||||
|
||||
* ZMQ_IDENTITY has been renamed to ZMQ_ROUTING_ID and ZMQ_CONNECT_RID has been
|
||||
renamed to ZMQ_CONNTECT_ROUTING_ID to disambiguate. ZMQ_IDENTITY and
|
||||
ZMQ_CONNECT_RID are still available to keep backward compatibility, and will
|
||||
be removed in a future release after further advance notice.
|
||||
|
||||
* DRAFT API change: zmq_poller_wait, zmq_poller_wait_all and zmq_poller_poll
|
||||
have been changed to be inline with other existing APIs that have a timeout
|
||||
to return EAGAIN instead of ETIMEDOUT as the errno value.
|
||||
See #2713 for details.
|
||||
|
||||
* Existing non-DRAFT socket types ZMQ_REP/REQ, ZMQ_ROUTER/DEALER and
|
||||
ZMQPUB/SUB, that were previously declared deprecated, have been reinstated
|
||||
as stable and supported. See #2699 for details.
|
||||
|
||||
* Tweetnacl: add support for, and use preferably if available, getrandom() as
|
||||
a simpler and less error-prone alternative to /dev/urandom on OSes where it
|
||||
is available (eg: Linux 3.18 with glibc 2.25).
|
||||
|
||||
* Curve: all remaining traces of debug output to console are now removed, and
|
||||
new DRAFT events are available to properly debug CURVE, PLAIN, GSSAPI and
|
||||
ZAP events and failures. See below for details on the new events.
|
||||
|
||||
* New DRAFT (see NEWS for 4.2.0) socket options:
|
||||
- ZMQ_GSSAPI_PRINCIPAL_NAMETYPE and ZMQ_GSSAPI_SERVICE_PRINCIPAL_NAMETYPE, for
|
||||
the corresponding GSSAPI features. Additional definitions for principal
|
||||
name types:
|
||||
- ZMQ_GSSAPI_NT_HOSTBASED
|
||||
- ZMQ_GSSAPI_NT_USER_NAME
|
||||
- ZMQ_GSSAPI_NT_KRB5_PRINCIPAL
|
||||
See doc/zmq_gssapi.txt for details.
|
||||
- ZMQ_BINDTODEVICE (Linux only), which will bind the socket(s) to the
|
||||
specified interface. Allows to use Linux VRF, see:
|
||||
https://www.kernel.org/doc/Documentation/networking/vrf.txt
|
||||
NOTE: requires the program to be ran as root OR with CAP_NET_RAW
|
||||
- ZMQ_ZAP_ENFORCE_DOMAIN, enables strict RFC 27 compatibility mode and makes
|
||||
the ZAP Domain mandatory when using security. See:
|
||||
https://rfc.zeromq.org/spec:27/ZAP
|
||||
See doc/zmq_setsockopt.txt and doc/zmq_getsockopt.txt for details.
|
||||
|
||||
* New DRAFT (see NEWS for 4.2.0) context options:
|
||||
- ZMQ_THREAD_AFFINITY_CPU_ADD and ZMQ_THREAD_AFFINITY_CPU_REMOVE (Posix only),
|
||||
to add and remove CPUs to the affinity set of the I/O threads. Useful to pin
|
||||
the background threads to specific CPUs.
|
||||
- ZMQ_THREAD_NAME_PREFIX (Posix only), to add a specific integer prefix to the
|
||||
background threads names, to easily identify them for debugging purposes.
|
||||
See doc/zmq_ctx_set.txt and doc/zmq_ctx_get.txt for details.
|
||||
|
||||
* New DRAFT (see NEWS for 4.2.0) message property name definitions to facilitate
|
||||
the use of zmq_msg_gets:
|
||||
- ZMQ_MSG_PROPERTY_ROUTING_ID
|
||||
- ZMQ_MSG_PROPERTY_SOCKET_TYPE
|
||||
- ZMQ_MSG_PROPERTY_USER_ID
|
||||
- ZMQ_MSG_PROPERTY_PEER_ADDRESS
|
||||
See doc/zmq_msg_gets.txt for details.
|
||||
|
||||
* New DRAFT (see NEWS for 4.2.0) API zmq_socket_get_peer_state, to be used to
|
||||
query the state of a specific peer (via routing-id) of a ZMQ_ROUTER socket.
|
||||
|
||||
* New DRAFT (see NEWS for 4.2.0) Socket Monitor events:
|
||||
- ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL, unknown system error and returns errno
|
||||
- ZMQ_EVENT_HANDSHAKE_SUCCEEDED, handshake was successful
|
||||
- ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL, protocol errors between peers or server
|
||||
and ZAP handler. Returns one of ZMQ_PROTOCOL_ERROR_* - see manpage for list
|
||||
- ZMQ_EVENT_HANDSHAKE_FAILED_AUTH, failed authentication, returns ZAP status
|
||||
These events trigger when the ZMTP security mechanism handshake is
|
||||
completed or failed. See doc/zmq_socket_monitor.txt for more information.
|
||||
|
||||
* New DRAFT (see NEWS for 4.2.0) zmq_proxy_steerable command 'STATISTICS' to
|
||||
retrieve stats about the amount of messages and bytes sent and received by
|
||||
the proxy. See doc/zmq_proxy_steerable.txt for more information.
|
||||
|
||||
* Add new autoconf --disable-libunwind option to stop building with libunwind
|
||||
even if it is available.
|
||||
|
||||
* Add new autoconf --disable-Werror option to avoid building with the Werror
|
||||
flag.
|
||||
|
||||
* Use pkg-config as the first method for finding and building with external
|
||||
optional dependencies such as libnorm, libpgm and gssapi.
|
||||
|
||||
* On Posix platform where the feature is available, name the ZMQ background
|
||||
threads to simplify debugging: "ZMQbg/<num_thread>"
|
||||
|
||||
* Improve performance of zmq_poller_* (and zmq_poll and zmq_proxy when building
|
||||
with DRAFT APIs enabled).
|
||||
|
||||
* The TCP unit tests have been refactored to bind and connect to random ports
|
||||
rather than hard-coded ones, to allow running tests in parallel.
|
||||
There are 6 exceptions where it is necessary to use an hard-coded port to
|
||||
test specific code paths that would not be exercised when binding to a
|
||||
wildcard port. These are listed in tests/testutil.hpp so that distributions
|
||||
can easily patch them if they wish to and so that they can be unique across
|
||||
all the tests, allowing parallel runs.
|
||||
The IPC unit tests have been changed as well to use unique socket file names
|
||||
per test, where before there were some clashes.
|
||||
|
||||
* Fixed #2349 - fix building with libsodium when using CMake
|
||||
|
||||
* Fixed #2334 - do not assert when tuning socket options fails due to network
|
||||
errors, but simply retry again when connecting or send a socket monitor
|
||||
ZMQ_EVENT_ACCEPT_FAILED event when binding
|
||||
|
||||
* Fixed #2341 - fix source files path in VS2015 solution
|
||||
|
||||
* Fixed #2344 - Note that on Windows with VS2012 it is mandatory to increase
|
||||
the default stack size to at least 2MB
|
||||
|
||||
* Fixed #2348 - ZMQ_ROUTER send with ZMQ_ROUTER_MANDATORY can be stuck in case of
|
||||
network problem
|
||||
|
||||
* Fixed #2358 - occasional abort on zmq_connect on Windows
|
||||
|
||||
* Fixed #2370 - zmq_curve_keypair should return an error on failure rather
|
||||
than ignoring them and always returning 0
|
||||
|
||||
* Fixed #2452 - __STDC_LIMIT_MACROS before precompiled headers causes VC++
|
||||
warning
|
||||
|
||||
* Fixed #2457 - fix building with libsodium in Visual Studio solutions
|
||||
|
||||
* Fixed #2466 - add const qualifier to internal and public API that does not
|
||||
modify parameters
|
||||
|
||||
* Fixed #2471 - do more checks for OOM conditions when dynamic allocations is
|
||||
used
|
||||
|
||||
* Fixed #2476 - assertion causes abort after ZAP stop at shutdown
|
||||
|
||||
* Fixed #2479 - improve zmq_poller performance on Windows
|
||||
|
||||
* Fixed #2481 - potential memory leaks due to ZMTP handshake failures
|
||||
|
||||
* Fixed #2531 - ZMQ_GSSAPI_PRINCIPAL sockopt has no effect on client side
|
||||
|
||||
* Fixed #2535 - add BUILD_SHARED and BUILD_STATIC options to CMake, both on by
|
||||
default, to toggle shared and static library builds
|
||||
|
||||
* Fixed #2537 - use SYSTEM_CLOCK on OSX and CLOCK_MONOTONIC elsewhere for
|
||||
internal timers to avoid races
|
||||
|
||||
* Fixed #2540 - new zmq_poller used by zmq_poll without DRAFTs
|
||||
|
||||
* Fixed #2552 - Fix WITH_DOC CMake build to avoid checking for asciidoc if the
|
||||
option is disabled
|
||||
|
||||
* Fixed #2567 - Memory leak in REP socket handling
|
||||
|
||||
* Fixed #2579 - Compilation issue on Windows with CMake + ninja
|
||||
|
||||
* Fixed #2588 - SIGBUS under 64-bit SunOS Sparc
|
||||
|
||||
* Fixed #2590 - crash when using ZMQ_IMMEDIATE and ZMQ_LINGER to non-zero
|
||||
|
||||
* Fixed #2601 - XPUB_MANUAL subscriptions not removed on peer term
|
||||
|
||||
* Fixed #2602 - intermittent memory leak for ZMQ_REQ/REP send/recv
|
||||
|
||||
* Fixed #2608 - CURVE server (connect) fails when client rebinds
|
||||
|
||||
* Fixed #2610 - print backtraces in mutual exclusion to avoid mixing
|
||||
different traces
|
||||
|
||||
* Fixed #2621 - add missing CMake files to distributable tarball
|
||||
|
||||
* Fixed #2630 - improve compatibility with OpenBSD w.r.t. IPV6_V6ONLY
|
||||
|
||||
* Fixed #2638 - note in INSTALL that when using Windows builds on Linux with
|
||||
Wine it is necessary to increase the minimum TCP buffers
|
||||
|
||||
* Fixed #2632 - Fix file descriptor leak when using Tweetnacl (internal NACL
|
||||
implementation) instead of Libsodium, and fix race condition when using
|
||||
multiple ZMQ contexts with Tweetnacl
|
||||
|
||||
* Fixed #2681 - Possible buffer overflow in CURVE mechanism handshake.
|
||||
NOTE: this was protected by an assert previously, so there is no security
|
||||
risk.
|
||||
|
||||
* Fixed #2704 - test_sockopt_hwm fails occasionally on Windows
|
||||
|
||||
* Fixed #2701 - pgm build via cmake doesn't link libzmq with libpgm
|
||||
|
||||
* Fixed #2711 - ZAP handler communication errors should be handled consistently
|
||||
|
||||
* Fixed #2723 - assertion in src\select.cpp:111 or hang on zmq_ctx_destroy on
|
||||
Windows
|
||||
|
||||
* Fixed #2728 - fix support O_CLOEXEC when building with CMake
|
||||
|
||||
* Fixed #2761 - improve compatibility with TrueOS (FreeBSD 12)
|
||||
|
||||
* Fixed #2764 - do not unlink IPC socket files when closing a socket to avoid
|
||||
race conditions
|
||||
|
||||
* Fixed #2770 - support lcov 1.13 and newer
|
||||
|
||||
* Fixed #2787 - add libiphlpapi to PKGCFG_LIBS_PRIVATE for static mingw builds
|
||||
|
||||
* Fixed #2788 - document that adding -DZMQ_STATIC is required for Windows
|
||||
static builds with Mingw
|
||||
|
||||
* Fixed #2789 - description of zmq_atomic_counter_value return value is cloned
|
||||
from zmq_atomic_counter_new
|
||||
|
||||
* Fixed #2791 - fix building with DRAFT APIs on CentOS 6
|
||||
|
||||
* Fixed #2794 - router_t methods should not allocate memory for lookup in
|
||||
outpipes
|
||||
|
||||
* Fixed #2809 - optimize select() usage on Windows
|
||||
|
||||
* Fixed #2816 - add CMake and autoconf check for accept4, as it is not
|
||||
available on old Linux releases, and fallback to accept + FD_CLOEXEC
|
||||
|
||||
* Fixed #2824 - ZMQ_REQ socket does not report ZMQ_POLLOUT when ZMQ_REQ_RELAXED
|
||||
is set
|
||||
|
||||
* Fixed #2827 - add support for Haiku
|
||||
|
||||
* Fixed #2840 - fix building with VS2008
|
||||
|
||||
* Fixed #2845 - correct the ZMQ_LINGER documentation to accurately reflect that
|
||||
the default value is -1 (infinite). It never was 30 second in any released
|
||||
version, it was only changed briefly and then changed back, but the manpage
|
||||
was not reverted.
|
||||
|
||||
* Fixed #2861 - CMake/MSVC: export ZMQ_STATIC when needed.
|
||||
|
||||
0MQ version 4.2.2 stable, released on 2017/02/18
|
||||
=============================================
|
||||
|
||||
* Improve compatibility with GNU Hurd
|
||||
|
||||
* Fixed #2286 - improve CMake on Windows documentation
|
||||
|
||||
* Fixed #1235 - improved compatibility with mingw64
|
||||
|
||||
* Improve zmq_proxy documentation to state it can return ETERM as well
|
||||
|
||||
* Fixed #1442 - SO_NOSIGPIPE and connection closing by peer race condition
|
||||
|
||||
* Improve CMake functionality on Windows: ZeroMQConfig.cmake generation CPack
|
||||
option, correct static library filename, ship FindSodium.cmake in tarball
|
||||
|
||||
* Fixed #2228 - setting HWM after connect on inproc transport leads to infinite
|
||||
HWM
|
||||
|
||||
* Add support for Visual Studio 2017
|
||||
|
||||
* New DRAFT (see NEWS for 4.2.0) zmq_has option "draft" option that returns
|
||||
true if the library was built with DRAFT enabled. Useful for FFI bindings.
|
||||
See doc/zmq_has.txt for more information
|
||||
|
||||
* Fixed #2321 - zmq_z85_decode does not validate its input. The function has
|
||||
been fixed to correctly follow RFC32 and return NULL if the input is invalid
|
||||
|
||||
* Fixed #2323 - clock_t related crash on Apple iOS 9.3.2 and 9.3.5
|
||||
|
||||
* Fixed #1801 - OSX: Cmake installs libzmq in a weird PATH
|
||||
|
||||
* Fixed potential divide by zero in zmq::lb_t::sendpipe
|
||||
|
||||
* Improve compatibility with OpenIndiana by skipping epoll and using poll/select
|
||||
|
||||
* Fix IPv4-in-IPv6 mapped addresses parsing error
|
||||
|
||||
|
||||
0MQ version 4.2.1 stable, released on 2016/12/31
|
||||
=============================================
|
||||
|
||||
* New DRAFT (see NEWS for 4.2.0) Socket Monitor events:
|
||||
- ZMQ_EVENT_HANDSHAKE_SUCCEED
|
||||
- ZMQ_EVENT_HANDSHAKE_FAILED
|
||||
These events trigger when the ZMTP security mechanism handshake is
|
||||
completed. See doc/zmq_socket_monitor.txt for more information.
|
||||
|
||||
* New DRAFT (see NEWS for 4.2.0) Context options:
|
||||
- ZMQ_MSG_T_SIZE
|
||||
See doc/zmq_ctx_get.txt for more information.
|
||||
|
||||
* Fixed #2268 - improved compatibility with mingw32
|
||||
|
||||
* Fixed #2254 - ZMQ_PUB compatibility with libzmq 2.x broken
|
||||
|
||||
* Fixed #2245 - added support for VS2017, Windows SDK 10.0.14393.0, toolset v141
|
||||
|
||||
* Fixed #2242 - file descriptors leaks on fork+exec
|
||||
|
||||
* Fixed #2239 - retired poller item crash from reaper thread
|
||||
|
||||
* Fixed #2234 - improved compatibility with AIX 7.1
|
||||
|
||||
* Fixed #2225 - cannot pick select for poller
|
||||
|
||||
* Fixed #2217 - CMake build uses library version as the ABI version
|
||||
|
||||
* Fixed #2208 - added support for ZMQ_TOS on IPv6
|
||||
|
||||
* Fixed #2200 - no documentation for ZMQ_SOCKS_PROXY
|
||||
|
||||
* Fixed #2199 - no documentation for zmq_curve_public
|
||||
|
||||
* Fixed #2196 - fixed build and runtime errors on kFreeBSD
|
||||
|
||||
|
||||
0MQ version 4.2.0 stable, released on 2016/11/04
|
||||
=============================================
|
||||
|
||||
* For Pieter. Thanks for making all of this possible.
|
||||
|
||||
"Tell them I was a writer.
|
||||
A maker of software.
|
||||
A humanist. A father.
|
||||
And many things.
|
||||
But above all, a writer.
|
||||
Thank You. :)"
|
||||
- Pieter Hintjens
|
||||
|
||||
* This release introduces new APIs, but it is ABI compatible with
|
||||
libzmq 4.1.2 and up.
|
||||
|
||||
* Note for ARM and SPARC users: an alignment problem in zmq_msg_t that could in
|
||||
some cases and on some CPUs cause a SIGBUS error was solved, but it requires
|
||||
a rebuild of your application against the 4.2.0 version of include/zmq.h.
|
||||
To clarify, this change does not affect the internals of the library but only
|
||||
the public definition of zmq_msg_t, so there is no ABI incompatibility.
|
||||
|
||||
* Security with Curve is now available by default thanks to Tweetnacl sources:
|
||||
https://tweetnacl.cr.yp.to/index.html
|
||||
Libsodium is still fully supported but has to be enabled with the build flag
|
||||
--with-libsodium. Distribution and package maintainers are encouraged to use
|
||||
libsodium so that the security implementation can be audited and maintained
|
||||
separately.
|
||||
|
||||
* New Context options:
|
||||
- ZMQ_MAX_MSGSZ
|
||||
- ZMQ_BLOCKY
|
||||
See doc/zmq_ctx_set.txt and doc/zmq_ctx_get.txt for details.
|
||||
|
||||
* New Socket options:
|
||||
- ZMQ_HANDSHAKE_IVL
|
||||
- ZMQ_SOCKS_PROXY
|
||||
- ZMQ_XPUB_NODROP
|
||||
- ZMQ_XPUB_MANUAL
|
||||
- ZMQ_XPUB_WELCOME_MSG
|
||||
- ZMQ_STREAM_NOTIFY
|
||||
- ZMQ_INVERT_MATCHING
|
||||
- ZMQ_HEARTBEAT_IVL
|
||||
- ZMQ_HEARTBEAT_TTL
|
||||
- ZMQ_HEARTBEAT_TIMEOUT
|
||||
- ZMQ_XPUB_VERBOSER
|
||||
- ZMQ_CONNECT_TIMEOUT
|
||||
- ZMQ_TCP_MAXRT
|
||||
- ZMQ_THREAD_SAFE
|
||||
- ZMQ_MULTICAST_MAXTPDU
|
||||
- ZMQ_VMCI_BUFFER_SIZE
|
||||
- ZMQ_VMCI_BUFFER_MIN_SIZE
|
||||
- ZMQ_VMCI_BUFFER_MAX_SIZE
|
||||
- ZMQ_VMCI_CONNECT_TIMEOUT
|
||||
- ZMQ_USE_FD
|
||||
See doc/zmq_setsockopt.txt and doc/zmq_getsockopt.txt for details.
|
||||
|
||||
* New CURVE helper function to derive z85 public key from secret key:
|
||||
zmq_curve_public
|
||||
|
||||
* New cross-platform atomic counter helper functions:
|
||||
zmq_atomic_counter_new, zmq_atomic_counter_set, zmq_atomic_counter_inc,
|
||||
zmq_atomic_counter_dec, zmq_atomic_counter_value, zmq_atomic_counter_destroy
|
||||
See doc/zmq_atomic_*.txt for details.
|
||||
|
||||
* New DRAFT APIs early-release mechanism. New APIs will be introduced early
|
||||
in public releases, and until they are stabilized and guaranteed not to
|
||||
change anymore they will be unavailable unless the new build flag
|
||||
--enable-drafts is used. This will allow developers and early adopters to
|
||||
test new APIs before they are finalized.
|
||||
NOTE: as the name implies, NO GUARANTEE is made on the stability of these APIs.
|
||||
They might change or disappear entirely. Distributions are recommended NOT to
|
||||
build with them.
|
||||
|
||||
New socket types have been introduced in DRAFT state:
|
||||
ZMQ_SERVER, ZMQ_CLIENT, ZMQ_RADIO, ZMQ_DISH, ZMQ_GATHER, ZMQ_SCATTER,
|
||||
ZMQ_DGRAM
|
||||
All these sockets are THREAD SAFE, unlike the existing socket types. They do
|
||||
NOT support multipart messages (ZMQ_SNDMORE/ZMQ_RCVMORE).
|
||||
ZMQ_RADIO, ZMQ_DISH and ZMQ_DGRAM also support UDP as transport,
|
||||
both unicast and multicast. See doc/zmq_udp.txt for more details.
|
||||
New methods to support the new socket types functionality:
|
||||
zmq_join, zmq_leave, zmq_msg_set_routing_id, zmq_msg_routing_id,
|
||||
zmq_msg_set_group, zmq_msg_group
|
||||
See doc/zmq_socket.txt for more details.
|
||||
|
||||
New poller mechanism and APIs have been introduced in DRAFT state:
|
||||
zmq_poller_new, zmq_poller_destroy, zmq_poller_add, zmq_poller_modify,
|
||||
zmq_poller_remove, zmq_poller_wait, zmq_poller_wait_all, zmq_poller_add_fd
|
||||
zmq_poller_modify_fd, zmq_poller_remove_fd
|
||||
and a new supporting struct typedef: zmq_poller_event_t
|
||||
They support existing socket type, new thread-safe socket types and file
|
||||
descriptors (cross-platform).
|
||||
Documentation will be made available in the future before these APIs are declared
|
||||
stable.
|
||||
|
||||
New cross-platform timers helper functions have been introduced in DRAFT state:
|
||||
zmq_timers_new, zmq_timers_destroy, zmq_timers_add, zmq_timers_cancel,
|
||||
zmq_timers_set_interval, zmq_timers_reset, zmq_timers_timeout,
|
||||
zmq_timers_execute
|
||||
and a new supporting callback typedef: zmq_timer_fn
|
||||
|
||||
* Many, many bug fixes. The most important fixes are backported and captured in the
|
||||
4.1.x and 4.0.x changelogs.
|
||||
|
||||
|
||||
0MQ version 4.2.0 rc1, released on 2016/11/01
|
||||
=============================================
|
||||
|
||||
* Many changes, see ChangeLog.
|
||||
|
||||
|
||||
0MQ version 4.1.6 stable, released on 2016/11/01
|
||||
================================================
|
||||
|
||||
* Fixed #2051 - getifaddrs can fail with ECONNREFUSED
|
||||
|
||||
* Fixed #2091 - testutil.hpp fails to build on Windows XP
|
||||
|
||||
* Fixed #2096 - add tests/CMakeLists.in and version.rc.in to dist tar
|
||||
|
||||
* Fixed #2107 - zmq_connect with IPv6 "source:port;dest:port" broken
|
||||
|
||||
* Fixed #2117 - ctx_term assert with inproc zmq_router connect-before-bind
|
||||
|
||||
* Fixed #2158 - Socket monitor uses internal Pair from multiple threads
|
||||
|
||||
* Fixed #2161 - messages dropped due to HWM race
|
||||
|
||||
* Fixed #1325 - alignment issue with zmq_msg_t causes SIGBUS on SPARC and ARM
|
||||
|
||||
|
||||
0MQ version 4.1.5 stable, released on 2016/06/17
|
||||
================================================
|
||||
|
||||
* Fixed #1673 - CMake on Windows put PDB in wrong directory.
|
||||
|
||||
* Fixed #1723 - Family is not set when resolving NIC on Android.
|
||||
|
||||
* Fixed #1608 - Windows 7 TCP slow start issue.
|
||||
|
||||
* Fixed #1806 - uninitialised read in curve getsockopt.
|
||||
|
||||
* Fixed #1807 - build broken with GCC 6.
|
||||
|
||||
* Fixed #1831 - potential assertion failure with latest libsodium.
|
||||
|
||||
* Fixed #1850 - detection issues with tweetnacl/libsodium.
|
||||
|
||||
* Fixed #1877 - Avoid terminating connections prematurely
|
||||
|
||||
* Fixed #1887 - zmq_bind IPv4 fallback still tries IPv6
|
||||
|
||||
* Fixed #1866 - fails to build on SunOS 5.10 / Solaris 10
|
||||
|
||||
* Fixed #919 - ZMQ_LINGER (related to #1877)
|
||||
|
||||
* Fixed #114 - cannot unbind with same endpoint with IPv6 enabled.
|
||||
|
||||
* Fixed #1952 - CMake scripts not part of release tarballs
|
||||
|
||||
* Fixed #1542 - Fix a crash on Windows when port 5905 is in use.
|
||||
|
||||
* Fixed #2021 - Fix building on sparc32.
|
||||
|
||||
|
||||
0MQ version 4.1.4 stable, released on 2015/12/18
|
||||
================================================
|
||||
|
||||
* Fixed #1315 - socket monitor hangs if bind/setsockopt failed.
|
||||
|
||||
* Fixed #1399 - assertion failure in tcp.cpp after network reconnect.
|
||||
|
||||
* Fixed #1632 - build failure using latest libsodium.
|
||||
|
||||
* Fixed #1644 - assertion failure in msg.cpp:390 on STREAM sockets.
|
||||
|
||||
* Fixed #1661 - does not handle IPv6 link local addresses.
|
||||
|
||||
|
||||
0MQ version 4.1.3 stable, released on 2015/08/17
|
||||
================================================
|
||||
|
||||
* Fixed #1532 - getsockopt ZMQ_RCVMORE now resets all bits instead of only 32
|
||||
|
||||
* Fixed #1445 - zmq::socket_base_t::connect fails on tcp ipv6 address
|
||||
|
||||
|
||||
0MQ version 4.1.2 stable, released on 2015/06/15
|
||||
================================================
|
||||
|
||||
* Added explicit reference to static link exception in every source file.
|
||||
|
||||
* Bumped ABI version to 5:0:0 since 4.1.x changed the ABI.
|
||||
|
||||
* Fixed STDINT event interface macros to work with CZMQ 3.0.
|
||||
|
||||
* Fixed installation of man pages when BUILD_DOC is not set.
|
||||
|
||||
* Fixed #1428 - regression on single-socket proxies.
|
||||
|
||||
|
||||
0MQ version 4.1.1 stable, released on 2015/06/02
|
||||
================================================
|
||||
|
||||
* Fixed #1208 - fix recursion in automake packaging.
|
||||
|
||||
* Fixed #1224 - crash when processing empty unsubscribe message.
|
||||
|
||||
* Fixed #1213 - properties files were missing from source packages.
|
||||
|
||||
* Fixed #1273 - V3 protocol handler vulnerable to downgrade attacks.
|
||||
|
||||
* Fixed #1347 - lack way to get peer address.
|
||||
|
||||
* Fixed #1362 - SUB socket sometimes fails to resubscribe properly.
|
||||
|
||||
* Fixed #1377, #1144 - failed with WSANOTINITIALISED in some cases.
|
||||
|
||||
* Fixed #1389 - PUB, PUSH sockets had slow memory leak.
|
||||
|
||||
* Fixed #1382 - zmq_proxy did not terminate if there were no readers.
|
||||
|
||||
|
||||
0MQ version 4.1.0 rc1, released on 2014/10/14
|
||||
=============================================
|
||||
|
||||
* All issues that were fixed in 4.0.x
|
||||
|
||||
* Improved client reconnection strategy on errors
|
||||
|
||||
* GSSAPI security mechanism
|
||||
|
||||
* SOCKS5 support (ZMQ_SOCKS_PROXY)
|
||||
|
||||
* ZMQ_ROUTER_HANDOVER
|
||||
|
||||
* ZMQ_TOS
|
||||
|
||||
* ZMQ_CONNECT_RID
|
||||
|
||||
* ZMQ_HANDSHAKE_IVL
|
||||
|
||||
* ZMQ_IDENTITY_FD
|
||||
|
||||
* ZMQ_XPUB_NODROP
|
||||
|
||||
* ZMQ_SRCFD and ZMQ_SHARED message options
|
||||
|
||||
* Message metadata -- zmq_msg_gets ()
|
||||
|
||||
* Probe library configuration -- zmq_has ()
|
||||
|
||||
|
||||
0MQ version 4.0.8 stable, released on 2016/06/17
|
||||
================================================
|
||||
|
||||
* Fixed LIBZMQ-949 - zmq_unbind fails for inproc and wildcard endpoints
|
||||
|
||||
* Fixed #1806 - uninitialised read in curve getsockopt.
|
||||
|
||||
* Fixed #1807 - build broken with GCC 6.
|
||||
|
||||
* Fixed #1877 - Avoid terminating connections prematurely
|
||||
|
||||
* Fixed #1887 - zmq_bind IPv4 fallback still tries IPv6
|
||||
|
||||
* Fixed #98 - don't require libssp without libsodium on Solaris
|
||||
|
||||
* Fixed #919 - ZMQ_LINGER (related to #1877)
|
||||
|
||||
* Fixed #139 - "tempnam" is deprecated.
|
||||
|
||||
|
||||
0MQ version 4.0.7 stable, released on 2015/06/15
|
||||
================================================
|
||||
|
||||
* Fixed #1428 - regression on single-socket proxies.
|
||||
|
||||
|
||||
0MQ version 4.0.6 stable, released on 2015/06/02
|
||||
================================================
|
||||
|
||||
* Fixed #1273 - V3 protocol handler vulnerable to downgrade attacks.
|
||||
|
||||
* Fixed #1362 - SUB socket sometimes fails to resubscribe properly.
|
||||
|
||||
* Fixed #1377, #1144 - failed with WSANOTINITIALISED in some cases.
|
||||
|
||||
* Fixed #1389 - PUB, PUSH sockets had slow memory leak.
|
||||
|
||||
* Fixed #1382 - zmq_proxy did not terminate if there were no readers.
|
||||
|
||||
|
||||
0MQ version 4.0.5 stable, released on 2014/10/14
|
||||
================================================
|
||||
|
||||
* Fixed #1191; CURVE mechanism does not verify short term nonces.
|
||||
|
||||
* Fixed #1190; stream_engine is vulnerable to downgrade attacks.
|
||||
|
||||
* Fixed #1088; assertion failure for WSAENOTSOCK on Windows.
|
||||
|
||||
* Fixed #1015; race condition while connecting inproc sockets.
|
||||
|
||||
* Fixed #994; bump so library number to 4.0.0
|
||||
|
||||
* Fixed #939, assertion failed: !more (fq.cpp:99) after many ZAP requests.
|
||||
|
||||
* Fixed #872; lost first part of message over inproc://.
|
||||
|
||||
* Fixed #797, keep-alive on Windows.
|
||||
|
||||
|
||||
0MQ version 4.0.4 stable, released on 2014/03/10
|
||||
================================================
|
||||
|
||||
Bug Fixes
|
||||
---------
|
||||
|
||||
* Fixed #909; out of tree build issue on Linux.
|
||||
|
||||
* Fixed #888; hangs on terminate when inproc connected but never bound.
|
||||
|
||||
* Fixed #868; assertion failure at ip.cpp:137 when using port scanner.
|
||||
|
||||
* Fixed #818; fix timestamp counter on s390/s390x.
|
||||
|
||||
* Fixed #817; only export zmq_* symbols.
|
||||
|
||||
* Fixed #797; fixed setting TCP keepalive on Windows.
|
||||
|
||||
* Fixed #775; compile error on Windows.
|
||||
|
||||
* Fixed #763; when talking to a ZMTP v1 peer (libzmq 2.2), a socket would
|
||||
send an extra identity frame at the start of the connection.
|
||||
|
||||
* Fixed LIBZMQ-576 - Crash closing a socket after zmq_msg_send returns
|
||||
EAGAIN (reverts LIBZMQ-497)
|
||||
|
||||
* Fixed LIBZMQ-584; subscription filters getting lost on reconnection.
|
||||
|
||||
|
||||
0MQ version 4.0.3 stable, released on 2013/11/24
|
||||
================================================
|
||||
|
||||
Bug Fixes
|
||||
---------
|
||||
|
||||
* Fixed test_many_sockets case, which failed when process socket limit
|
||||
was 1024.
|
||||
|
||||
|
||||
0MQ version 4.0.2 stable, released on 2013/11/24
|
||||
================================================
|
||||
|
||||
Bug Fixes
|
||||
---------
|
||||
|
||||
* Fixed LIBZMQ-583 - improved low-res timer for Windows
|
||||
* Fixed LIBZMQ-578 - z85_decode was extremely slow
|
||||
* Fixed LIBZMQ-577 - fault in man pages.
|
||||
* Fixed LIBZMQ-574 - assertion failure when ran out of system file handles
|
||||
* Fixed LIBZMQ-571 - test_stream failing in some cases
|
||||
* Fixed LIBZMQ-569 - Socket server crashes with random client data and when
|
||||
talking to 2.2 versions
|
||||
* Fixed LIBZMQ-39 - Bad file descriptor during shutdown
|
||||
* Pulled expected failing test_linger.cpp from release
|
||||
* Reduced pause time in tests to allow "make check" to run faster
|
||||
|
||||
|
||||
0MQ version 4.0.1 stable, released on 2013/10/08
|
||||
================================================
|
||||
|
||||
Changes
|
||||
-------
|
||||
|
||||
* Updated CURVE mechanism to track revised RFC 27 (INITIATE vouch).
|
||||
|
||||
The INITIATE command vouch box is Box[C',S](C->S') instead of
|
||||
Box[C'](C->S), to reduce the risk of client impersonation, as per
|
||||
https://codesinchaos.wordpress.com/2012/09/09/curvecp-1/.
|
||||
|
||||
* Fixed LIBZMQ-567, adding abstract namespaces for IPC sockets on Linux.
|
||||
|
||||
Converts an initial strudel or "at sign" (@) in the Unix socket path to
|
||||
a NULL character ('\0') indicating that the socket uses the abstract
|
||||
namespace instead of the filesystem namespace. For instance, binding a
|
||||
socket to 'ipc://@/tmp/tester' will not create a file associated with
|
||||
the socket whereas binding to 'ipc:///tmp/tester' will create the file
|
||||
/tmp/tester. See issue 567 for more information.
|
||||
|
||||
* Added zmq_z85_encode and zmq_z85_decode to core libzmq API.
|
||||
|
||||
* Added zmq_curve_keypair to core libzmq API.
|
||||
|
||||
* Bumped library ABI version to 4:0:1.
|
||||
|
||||
Bug fixes
|
||||
---------
|
||||
|
||||
* Fixed some build/test errors on OS/X + Clang++.
|
||||
|
||||
* Fixed LIBZMQ-565, typo in code.
|
||||
|
||||
* Fixed LIBZMQ-566, dealer-to-router connections sometimes failing.
|
||||
|
||||
* Fixed builds for AIX, MSVC 2008, OS/X with clang++, Solaris.
|
||||
|
||||
* Improved CURVE handshake error handling.
|
||||
|
||||
|
||||
0MQ version 4.0.0 (RC1), released on 2013/09/20
|
||||
===============================================
|
||||
|
||||
Major changes
|
||||
-------------
|
||||
|
||||
* New wire level protocol, ZMTP/3.0, see http://rfc.zeromq.org/spec:23.
|
||||
Does not yet implement the SUBSCRIBE, CANCEL, PING, and PONG commands.
|
||||
|
||||
* New security framework, from plain user+password to strong encryption,
|
||||
see section below. See http://hintjens.com/blog:49 for a tutorial.
|
||||
|
||||
* New ZMQ_STREAM socket type for working as a TCP client or server. See:
|
||||
tests/test_stream.cpp.
|
||||
|
||||
Improvements
|
||||
------------
|
||||
|
||||
* You can now connect to an inproc:// endpoint that does not already
|
||||
exist. This means inproc:// no longer needs careful set-up, but it may
|
||||
break code that relied on the old behaviour. See:
|
||||
tests/test_inproc_connect.cpp.
|
||||
|
||||
* Libzmq now checks socket types at connection time, so that trying to
|
||||
connect a 'wrong' socket type will fail.
|
||||
|
||||
* New zmq_ctx_shutdown API method will shutdown a context and send ETERM
|
||||
to blocking calls, without blocking. Use zmq_ctx_term to finalise the
|
||||
process.
|
||||
|
||||
* The regression test suite has been significantly extended and improved.
|
||||
|
||||
* Contexts can now be terminated in forked child processes. See:
|
||||
tests/test_fork.cpp.
|
||||
|
||||
* zmq_disconnect now respects the linger setting on sockets.
|
||||
|
||||
* New zmq_send_const API method to send constant data (without copying).
|
||||
See: tests/test_inproc_connect.cpp.
|
||||
|
||||
* Added CMake support for static libraries.
|
||||
|
||||
* Added test cases for socket semantics as defined in RFCs 28, 29, 30, 31.
|
||||
See: tests/test_spec_*.cpp.
|
||||
|
||||
* New socket option, ZMQ_PROBE_ROUTER triggers an empty message on connect.
|
||||
See: tests/test_probe_router.cpp.
|
||||
|
||||
* New socket option, ZMQ_REQ_CORRELATE allows for correlation of replies
|
||||
from a REP socket. See: tests/test_req_correlate.cpp.
|
||||
|
||||
* New socket option, ZMQ_REQ_RELAXED, lets you disable the state machine
|
||||
on a REQ socket, so you can send multiple requests without waiting for
|
||||
replies, and without getting an EFSM error. See:
|
||||
tests/test_req_relaxed.cpp.
|
||||
|
||||
* New socket option, ZMQ_CONFLATE restricts the outgoing and incoming
|
||||
socket buffers to a single message. See: tests/test_conflate.cpp.
|
||||
|
||||
Deprecated Options
|
||||
------------------
|
||||
|
||||
* ZMQ_IPV4ONLY deprecated and renamed to ZMQ_IPV6 so that options are
|
||||
consistently "off" by default.
|
||||
|
||||
* ZMQ_DELAY_ATTACH_ON_CONNECT deprecated, and renamed to ZMQ_IMMEDIATE.
|
||||
See: tests/test_immediate.cpp.
|
||||
|
||||
Security Framework
|
||||
------------------
|
||||
|
||||
Based on new ZMTP wire level protocol that negotiates a security
|
||||
"mechanism" between client and server before exchanging any other data.
|
||||
|
||||
Security mechanisms are extensible. ZMTP defines three by default:
|
||||
|
||||
* NULL - classic ZeroMQ, with no authentication. See
|
||||
http://rfc.zeromq.org/spec:23.
|
||||
|
||||
* PLAIN - plain-text username + password authentication. See
|
||||
http://rfc.zeromq.org/spec:24.
|
||||
|
||||
* CURVE - secure authentication and encryption based on elliptic curve
|
||||
cryptography, using the Curve25519 algorithm from Daniel Bernstein and
|
||||
based on CurveCP's security handshake. See http://rfc.zeromq.org/spec:25,
|
||||
http://rfc.zeromq.org/spec:26, and http://curvecp.org.
|
||||
|
||||
Authentication is done by pluggable "authenticators" that connect to libzmq
|
||||
over an inproc endpoint, see http://rfc.zeromq.org/spec:27.
|
||||
|
||||
Socket options to configure PLAIN security on client or server:
|
||||
|
||||
* ZMQ_PLAIN_SERVER, ZMQ_PLAIN_USERNAME, ZMQ_PLAIN_PASSWORD. See
|
||||
tests/test_security_plain.
|
||||
|
||||
Socket options to configure CURVE security on client or server:
|
||||
|
||||
* ZMQ_CURVE_SERVER, ZMQ_CURVE_PUBLICKEY, ZMQ_CURVE_SECRETKEY,
|
||||
ZMQ_CURVE_SERVERKEY. See tests/test_security_curve.cpp.
|
||||
|
||||
Socket options to configure "domain" for ZAP handler:
|
||||
|
||||
* ZMQ_ZAP_DOMAIN, see tests/test_security_null.cpp.
|
||||
|
||||
Support for encoding/decoding CURVE binary keys to ASCII:
|
||||
|
||||
* zmq_z85_encode, zmq_z85_decode.
|
||||
|
||||
Other issues addressed in this release
|
||||
--------------------------------------
|
||||
|
||||
* LIBZMQ-525 Multipart upstreaming from XSUB to XPUB
|
||||
|
||||
|
||||
0MQ version 3.2.4 stable, released on 2013/09/20
|
||||
================================================
|
||||
|
||||
* LIBZMQ-84 (Windows) Assertion failed: Address already in use at signaler.cpp:80
|
||||
* LIBZMQ-456 ZMQ_XPUB_VERBOSE does not propagate in a tree of XPUB/XSUB devices
|
||||
* LIBZMQ-532 (Windows) critical section not released on error
|
||||
* LIBZMQ-569 Detect OpenPGM 5.2 system library
|
||||
* LIBZMQ-563 Subscribers sometimes stopped receiving messages (aka LIBZMQ-541)
|
||||
* LIBZMQ-XXX Added support for Travis Continuous Integration
|
||||
* LIBZMQ-XXX Several improvements to MSVC support
|
||||
|
||||
|
||||
0MQ version 3.2.3 stable, released on 2013/05/02
|
||||
================================================
|
||||
|
||||
Issues addressed in this release
|
||||
--------------------------------
|
||||
|
||||
* LIBZMQ-526 Assertion failure "Invalid argument (tcp_connecter.cpp:285)"
|
||||
* LIBZMQ-446 Setting the DSCP bits by default causes CAP_NET_ADMIN error
|
||||
* LIBZMQ-496 Crash on heavy socket opening/closing: Device or resource busy (mutex.hpp:90)
|
||||
* LIBZMQ-462 test_connect_delay fails at test_connect_delay.cpp:80
|
||||
* LIBZMQ-497 Messages getting dropped
|
||||
* LIBZMQ-488 signaler.cpp leaks the win32 Event Handle
|
||||
* LIBZMQ-476 zmq_disconnect has no effect for inproc sockets
|
||||
* LIBZMQ-475 zmq_disconnect does not sent unsubscribe messages
|
||||
|
||||
|
||||
0MQ version 3.2.2 stable, released on 2012/11/23
|
||||
================================================
|
||||
|
||||
Issues addressed in this release
|
||||
--------------------------------
|
||||
|
||||
* LIBZMQ-384 No meta data for ZMQ_EVENT_DISCONNECTED monitor event
|
||||
* LIBZMQ-414 Error in ARM/Thumb2 assembly (atomic_ptr.hpp)
|
||||
* LIBZMQ-417 zmq_assert (!incomplete_in) in session_base.cpp 228
|
||||
* LIBZMQ-447 socket_base_t::recv() packet loss and memory leak at high receiving rate
|
||||
* LIBZMQ-448 Builds fail on older versions of GCC
|
||||
* LIBZMQ-449 Builds fail on AIX
|
||||
* LIBZMQ-450 lt-test_monitor: fails with assertion at test_monitor.cpp:81
|
||||
* LIBZMQ-451 ZMQ_ROUTER_MANDATORY blocks forever
|
||||
* LIBZMQ-452 test_connect_delay.cpp:175:12: error: 'sleep' was not declared in this scope
|
||||
* LIBZMQ-458 lt-test_router_mandatory fails with assertion at test_router_mandatory.cpp:53
|
||||
* LIBZMQ-459 Assertion failed: encoder (stream_engine.cpp:266
|
||||
* LIBZMQ-464 PUB socket with HWM set leaks memory
|
||||
* LIBZMQ-465 PUB/SUB results in 80-90% of CPU load
|
||||
* LIBZMQ-468 ZMQ_XPUB_VERBOSE & unsubscribe
|
||||
* LIBZMQ-472 Segfault in zmq_poll in REQ to ROUTER dialog
|
||||
|
||||
|
||||
0MQ version 3.2.1 (RC2), released on 2012/10/15
|
||||
===============================================
|
||||
|
||||
Issues addressed in this release
|
||||
--------------------------------
|
||||
|
||||
* Fixed issue xxx - handle insufficient resources on accept() properly.
|
||||
* Fixed issue 443 - added ZMQ_XPUB_VERBOSE setsocket option.
|
||||
* Fixed issue 433 - ZeroMQ died on receiving EPIPE
|
||||
* Fixed issue 423 - test_pair_tcp hangs
|
||||
* Fixed issue 416 - socket_base: fix 'va_list' has not been declared error
|
||||
* Fixed issue 409 - Pub-sub interoperability between 2.x and 3.x.
|
||||
* Fixed issue 404 - zmq_term can not safely be re-entered with pgm transport
|
||||
* Fixed issue 399 - zmq_ctx_set_monitor callback is not works properly
|
||||
* Fixed issue 393 - libzmq does not build on Android (socklen_t signed comparison)
|
||||
* Fixed issue 392 - Interaction with pyzmq on Android
|
||||
* Fixed issue 389 - Assertion failure in mtrie.cpp:317
|
||||
* Fixed issue 388 - tests/test_monitor.cpp has no newline at EOF (causes compile error)
|
||||
* Fixed issue 387 - "sa_family_t sa_family;" in pgm_socket.cpp is unused variable
|
||||
* Fixed issue 385 - Rework ZMQ_FAIL_UNROUTABLE socket option to actually work
|
||||
* Fixed issue 382 - Current libzmq doesn't compile on Android NDK
|
||||
* Fixed issue 377 - ZeroMQ will not build on Windows with OpenPGM
|
||||
* Fixed issue 375 - error: unused variable 'sa_family'
|
||||
* Fixed issue 373 - Unable to build libzmq/zeromq3.x on AIX7
|
||||
* Fixed issue 372 - Unable to build libzmq/zeromq3.x on HPUX 11iv3
|
||||
* Fixed issue 371 - Unable to build libzmq/zeromq3.x on RHEL5/SLES10
|
||||
* Fixed issue 329 - wsa_error_to_errno() calls abort() on WSAEACCES
|
||||
* Fixed issue 309 - Assertion failed: options.recv_identity (socket_base.cpp:864)
|
||||
* Fixed issue 211 - Assertion failed: msg_->flags & ZMQ_MSG_MORE (rep.cpp:81)
|
||||
|
||||
API changes
|
||||
-----------
|
||||
|
||||
* zmq_device () deprecated and replaced by zmq_proxy ().
|
||||
* zmq_ctx_set_monitor () replaced by zmq_socket_monitor ().
|
||||
* ZMQ_ROUTER_BEHAVIOR/ZMQ_FAIL_UNROUTABLE renamed experimentally to
|
||||
ZMQ_ROUTER_MANDATORY.
|
||||
|
||||
|
||||
0MQ version 3.2.0 (RC1), released on 2012/06/05
|
||||
===============================================
|
||||
|
||||
Bug fixes
|
||||
---------
|
||||
|
||||
* Fixed issue 264 - Potential bug with linger, messages dropped during
|
||||
socket close.
|
||||
|
||||
* Fixed issue 293 - libzmq doesn't follow the ZMTP/1.0 spec (did not
|
||||
set reserved bits to 0).
|
||||
|
||||
* Fixed issue 303 - Assertion failure in pgm_sender.cpp:102.
|
||||
|
||||
* Fixed issue 320 - Assertion failure in connect_session.cpp:96 when
|
||||
connecting epgm to an invalid endpoint.
|
||||
|
||||
* Fixed issue 325 - Assertion failure in xrep.cpp:93, when two sockets
|
||||
connect using the same identity.
|
||||
|
||||
* Fixed issue 327 - Assertion failure in mtrie.cpp:246, when
|
||||
unsubscribing from channel.
|
||||
|
||||
* Fixed issue 346 - Assertion failure in signaler.cpp:155, when using a
|
||||
closed socket.
|
||||
|
||||
* Fixed issue 328 - unsubscribe wrongly clears multiple subscriptions.
|
||||
|
||||
* Fixed issue 330 - IPC listener does not remove unix domain stream file
|
||||
when terminated.
|
||||
|
||||
* Fixed issue 334 - Memory leak in session_base.cpp:59.
|
||||
|
||||
* Fixed issue 369 - ROUTER cannot close/reopen while DEALER connected.
|
||||
|
||||
Operating systems
|
||||
-----------------
|
||||
|
||||
* Fixed issue 301 - HPUX 11iv2 - build fails, CLOCK_MONOTONIC
|
||||
undefined.
|
||||
|
||||
* Fixed issue 324 - OS/X - build fails, ECANTROUTE undefined.
|
||||
|
||||
* Fixed issue 368 - Solaris / Sun C++ - build fails, no insert method
|
||||
in multimap classes.
|
||||
|
||||
* Fixed issue 366 - Windows - ports not freed after crash.
|
||||
|
||||
* Fixed issue 355 - Windows - build fails, MSVC solution file is out of
|
||||
date.
|
||||
|
||||
* Fixed issue 331 - FreeBSD 8 and 9 - getaddrinfo fails with
|
||||
EAI_BADFLAGS on AI_V4MAPPED flag.
|
||||
|
||||
* Fixed issue xxx - Added support for WinCE.
|
||||
|
||||
Performance
|
||||
-----------
|
||||
|
||||
* Fixed issue xxx - Implemented atomic operations for ARMv7a (runs 15-20% faster).
|
||||
|
||||
API changes
|
||||
-----------
|
||||
|
||||
* Fixed issue 337 - Cleaned-up context API:
|
||||
|
||||
zmq_ctx_new() - create new context (will deprecate zmq_init)
|
||||
zmq_ctx_destroy() - destroy context (will deprecate zmq_term)
|
||||
zmq_ctx_set() - set context property
|
||||
zmq_ctx_get() - get context property
|
||||
|
||||
* Fixed issue xxx - Cleaned-up message API:
|
||||
|
||||
zmq_msg_send() - send a message (will deprecate zmq_sendmsg)
|
||||
zmq_msg_recv() - receive a message (will deprecate zmq_recvmsg)
|
||||
zmq_msg_more() - indicate whether this is final part of message
|
||||
zmq_msg_get() - get message property
|
||||
zmq_msg_set() - set message property
|
||||
|
||||
* Fixed issue xxx - Added context monitoring API:
|
||||
|
||||
zmq_ctx_set_monitor() - configure monitor callback.
|
||||
|
||||
* Fixed issue xxx - Added unbind/disconnect API:
|
||||
|
||||
zmq_unbind() - unbind socket.
|
||||
zmq_disconnect() - disconnect socket.
|
||||
|
||||
* Fixed issue xxx - Added ZMQ_TCP_ACCEPT_FILTER setsockopt() for listening TCP sockets.
|
||||
|
||||
* Fixed issue 336 - Removed sys: transport.
|
||||
|
||||
* Fixed issue 333 - Added zmq_device function back to API (was removed
|
||||
in 3.0).
|
||||
|
||||
* Fixed issue 340 - Add support for MAX_SOCKETS to new context API.
|
||||
|
||||
|
||||
OMQ version 3.1.0 (beta), released on 2011/12/18
|
||||
================================================
|
||||
|
||||
General information
|
||||
-------------------
|
||||
|
||||
Based on community consensus, the 0MQ 3.1.x release reverts a number of
|
||||
features introduced in version 3.0. The major reason for these changes is
|
||||
improving backward compatibility with 0MQ 2.1.x.
|
||||
|
||||
Development of the 0MQ 3.0.x series will be discontinued, and users are
|
||||
encouraged to upgrade to 3.1.
|
||||
|
||||
The 0MQ 3.1.x releases use ABI version 3.
|
||||
|
||||
Reverted functionality
|
||||
----------------------
|
||||
|
||||
The following functionality present in 0MQ 3.0 has been reverted:
|
||||
|
||||
* Wire format changes. The 0MQ 3.1 wire format is identical to that of 0MQ
|
||||
2.1.
|
||||
|
||||
* LABELs and COMMANDs have been removed.
|
||||
|
||||
* Explicit identies are re-introduced, however they can be used only for
|
||||
explicit routing, not for durable sockets.
|
||||
|
||||
* The ZMQ_ROUTER and ZMQ_DEALER socket types are once again aliases for
|
||||
ZMQ_XREQ and ZMQ_XREP.
|
||||
|
||||
New functionality
|
||||
-----------------
|
||||
|
||||
* The zmq_getmsgopt() function has been introduced.
|
||||
|
||||
* Experimental IPv6 support has been introduced. This is disabled by
|
||||
default, see the zmq_setsockopt() documentation for enabling it.
|
||||
|
||||
Other changes
|
||||
-------------
|
||||
|
||||
* The default HWM for all socket types has been set to 1000.
|
||||
|
||||
* Many bug fixes.
|
||||
|
||||
Building
|
||||
--------
|
||||
|
||||
* The dependency on libuuid has been removed.
|
||||
|
||||
* Support for building on Android, and with MSVC 10 has been added.
|
||||
|
||||
0MQ version 3.0.0 (alpha), released on 2011/07/12
|
||||
=================================================
|
||||
|
||||
New functionality
|
||||
-----------------
|
||||
|
||||
* A zmq_ctx_set_monitor() API to register a callback / event sink for changes
|
||||
in socket state.
|
||||
|
||||
* POSIX-compliant zmq_send and zmq_recv introduced (uses raw buffer
|
||||
instead of message object).
|
||||
|
||||
* ZMQ_MULTICAST_HOPS socket option added. Sets the appropriate field in
|
||||
IP headers of PGM packets.
|
||||
|
||||
* Subscription forwarding. Instead of filtering on consumer, the
|
||||
subscription is moved as far as possible towards the publisher and
|
||||
filtering is done there.
|
||||
|
||||
* ZMQ_XPUB, ZMQ_XSUB introduced. Allow to create subscription-
|
||||
forwarding-friendly intermediate devices.
|
||||
|
||||
* Add sockopt ZMQ_RCVTIMEO/ZMQ_SNDTIMEO. Allow to set timeout for
|
||||
blocking send/recv calls.
|
||||
|
||||
* A new LABEL flag was added to the wire format. The flag distinguishes
|
||||
message parts used by 0MQ (labels) from user payload message parts.
|
||||
|
||||
* There is a new wire format for the REQ/REP pattern. First, the empty
|
||||
bottom-of-the-stack message part is not needed any more, the LABEL
|
||||
flag is used instead. Secondly, peer IDs are 32-bit integers rather
|
||||
than 17-byte UUIDs.
|
||||
|
||||
* The REQ socket now drops duplicate replies.
|
||||
|
||||
* Outstanding requests & replies associated with a client are dropped
|
||||
when the clients dies. This is a performance optimisation.
|
||||
|
||||
* Introduced ZMQ_ROUTER and ZMQ_DEALER sockets. These mimic the
|
||||
functionality of ZMQ_ROUTER and ZMQ_DEALER in 0MQ/2.1.x. Guarantees
|
||||
backward compatibility for exsiting code.
|
||||
|
||||
* Removed dependency on OS socketpair buffer size. No more asserts in
|
||||
mailbox.cpp because of low system limit of sockepair buffer size.
|
||||
|
||||
API improvements
|
||||
----------------
|
||||
|
||||
* Obsolete constants ZMQ_UPSTREAM and ZMQ_DOWNSTREAM removed. Use
|
||||
ZMQ_PUSH and ZMQ_PULL instead.
|
||||
|
||||
* Timeout in zmq_poll is in milliseconds instead of microseconds. This
|
||||
makes zmq_poll() compliant with POSIX poll()
|
||||
|
||||
* ZMQ_MCAST_LOOP removed. There's no support for multicast over
|
||||
loopback any more. Use IPC or TCP isntead.
|
||||
|
||||
* zmq_send/zmq_recv was renamed zmq_sendmsg/zmq_recvmsg.
|
||||
|
||||
* ZMQ_RECOVERY_IVL and ZMQ_RECOVERY_IVL_MSEC reconciled. The new option
|
||||
is named ZMQ_RECOVERY_IVL and the unit is milliseconds.
|
||||
|
||||
* Option types changed. Most of the numeric types are now represented
|
||||
as 'int'.
|
||||
|
||||
* ZMQ_HWM split into ZMQ_SNDHWM and ZMQ_RCVHWM. This makes it possible
|
||||
to control message flow separately for each direction.
|
||||
|
||||
* ZMQ_NOBLOCK renamed ZMQ_DONTWAIT. That makes it POSIX-compliant.
|
||||
|
||||
Less is More
|
||||
------------
|
||||
|
||||
* Pre-built devices and zmq_device() removed. Should be made available
|
||||
as a separate project(s).
|
||||
|
||||
* ZMQ_SWAP removed. Writing data to disk should be done on top of 0MQ,
|
||||
on inside it.
|
||||
|
||||
* C++ binding removed from the core. Now it's a separate project, same
|
||||
as any other binding.
|
||||
|
||||
Bug fixes
|
||||
---------
|
||||
|
||||
* Many.
|
||||
|
||||
Building
|
||||
--------
|
||||
|
||||
* Make pkg-config dependency conditional.
|
||||
|
||||
Distribution
|
||||
------------
|
||||
|
||||
* Removed Debian packaging, which is now available at packages.debian.org
|
||||
or via apt-get.
|
||||
|
||||
|
||||
0MQ version 2.2.0 (Stable), released on 2012/04/04
|
||||
==================================================
|
||||
|
||||
Changes
|
||||
-------
|
||||
|
||||
* Fixed issue 349, add send/recv timeout socket options.
|
||||
|
||||
Bug fixes
|
||||
---------
|
||||
|
||||
* Fixed issue 301, fix builds on HP-UX 11iv3 when using either gcc or aCC.
|
||||
|
||||
* Fixed issue 305, memory leakage when using dynamic subscriptions.
|
||||
|
||||
* Fixed issue 332, libzmq doesn't compile on Android NDK.
|
||||
|
||||
* Fixed issue 293, libzmq doesn't follow ZMTP/1.0 spec.
|
||||
|
||||
* Fixed issue 342, cannot build against zmq.hpp under C++11.
|
||||
|
||||
|
||||
0MQ version 2.1.11 (Stable), released on 2011/12/18
|
||||
===================================================
|
||||
|
||||
Bug fixes
|
||||
---------
|
||||
|
||||
* Fixed issue 290, zmq_poll was using system time instead of monotonic
|
||||
clock (Mika Fischer).
|
||||
|
||||
* Fixed issue 281, crash on heavy socket creation - assertion failure in
|
||||
mutex.hpp:91. (Mika Fischer).
|
||||
|
||||
* Fixed issue 273, O_CLOEXEC flag used in ip.cpp:192 is supported only
|
||||
on Linux kernels 2.6.27+
|
||||
|
||||
* Fixed issue 261, assertion failure in kqueue.cpp:76.
|
||||
|
||||
* Fixed issue 269, faulty diagnostic code in 2.1.10.
|
||||
|
||||
* Fixed issue 254, assertion failure at tcp_socket.cpp:229 on ENOTCONN.
|
||||
|
||||
Changes
|
||||
-------
|
||||
|
||||
* Now builds properly on AIX 6.1 (AJ Lewis).
|
||||
|
||||
* Builds using libdcekt on HP-UX (AJ Lewis).
|
||||
|
||||
* New upstream OpenPGM maintenance release 5.1.118.
|
||||
|
||||
* Enabled debugging on assertion failure on Windows (Paul Betts).
|
||||
|
||||
|
||||
0MQ version 2.1.10 (Stable), released on 2011/10/03
|
||||
===================================================
|
||||
|
||||
Bug fixes
|
||||
---------
|
||||
|
||||
* Fixed issue 140, SWAP failed with assertion failure in pipe.cpp:187
|
||||
if the current directory was not writeable. Behavior now is to return
|
||||
-1 at zmq_setsockopt in this situation.
|
||||
|
||||
* Fixed issue 207, assertion failure in zmq_connecter.cpp:48, when an
|
||||
invalid zmq_connect() string was used, or the hostname could not be
|
||||
resolved. The zmq_connect() call now returns -1 in both those cases.
|
||||
|
||||
* Fixed issue 218, sockets not opened with SOCK_CLOEXEC, causing fork/exec
|
||||
to sit on sockets unnecessarily.
|
||||
|
||||
* Fixed issue 250, build errors on Windows (Mikko Koppanen).
|
||||
|
||||
* Fixed issue 252, assertion failure in req.cpp:87 and req.cpp:88 (Mikko
|
||||
Koppanen).
|
||||
|
||||
|
||||
0MQ version 2.1.9 (Stable), released on 2011/08/29
|
||||
==================================================
|
||||
|
||||
Bug fixes
|
||||
---------
|
||||
|
||||
* Fixed issue 240, assertion failure in pgm_socket.cpp:437.
|
||||
|
||||
* Fixed issue 238, assertion failure in zmq.cpp:655, when zmq_poll is
|
||||
used on an empty set, on Windows.
|
||||
|
||||
* Fixed issue 239, assertion failure in zmq.cpp:223, when ZMQ_SWAP was
|
||||
used with explicit identities and multiple SUB sockets.
|
||||
|
||||
* Fixed issue 236, zmq_send() and zmq_recv() did not always return
|
||||
error conditions such as EFSM properly. This bug was introduced in
|
||||
version 2.1.8 by the backport of changes for issue 231.
|
||||
|
||||
Building
|
||||
--------
|
||||
|
||||
* 0MQ support for Android added (Bill Roberts, Mikko Koppanen).
|
||||
|
||||
|
||||
0MQ version 2.1.8 (RC), released on 2011/07/28
|
||||
==============================================
|
||||
|
||||
Bug fixes
|
||||
---------
|
||||
|
||||
* Fixed issue 223, assertion failure in tcp_connecter.cpp:300 when
|
||||
connecting to a server that is on an unreachable network (errno is
|
||||
equal to ENETUNREACH).
|
||||
|
||||
* Fixed issue 228, assertion failure at rep.cpp:88 when HWM was reached.
|
||||
|
||||
* Fixed issue 231, assertion failure at mailbox.cpp:183 when too many
|
||||
pending socketpair operations were queued (major backport from 3.0).
|
||||
|
||||
* Fixed issue 234, assertion failure at mailbox.cpp:77 when Ctrl-C was
|
||||
used (only affected git master following backport for 231).
|
||||
|
||||
* Fixed issue 230, SIGPIPE killing servers when client disconnected, hit
|
||||
OS/X only.
|
||||
|
||||
Note: this release was renamed "release candidate" due to issue 236,
|
||||
fixed in 2.1.9.
|
||||
|
||||
|
||||
0MQ version 2.1.7 (Stable), released on 2011/05/12
|
||||
==================================================
|
||||
|
||||
Bug fixes
|
||||
---------
|
||||
|
||||
* Fixed issue 188, assert when closing socket that had unread multipart
|
||||
data still on it (affected PULL, SUB, ROUTER, and DEALER sockets).
|
||||
|
||||
* Fixed issue 191, message atomicity issue with PUB sockets (an old issue).
|
||||
|
||||
* Fixed issue 199 (affected ROUTER/XREP sockets, an old issue).
|
||||
|
||||
* Fixed issue 206, assertion failure in zmq.cpp:223, affected all sockets
|
||||
(bug was introduced in 2.1.6 as part of message validity checking).
|
||||
|
||||
* Fixed issue 211, REP socket asserted if sent malformed envelope (old issue
|
||||
due to abuse of assertions for error checking).
|
||||
|
||||
* Fixed issue 212, reconnect failing after resume from sleep on Windows
|
||||
(due to not handling WSAENETDOWN).
|
||||
|
||||
* Properly handle WSAENETUNREACH on Windows (e.g. if client connects
|
||||
before server binds).
|
||||
|
||||
* Fixed memory leak with threads on Windows.
|
||||
|
||||
Changes
|
||||
-------
|
||||
|
||||
* Checks zmq_msg_t validity at each operation.
|
||||
|
||||
* Inproc performance tests now work on Windows.
|
||||
|
||||
* PGM wire format specification improved in zmq_pgm(7)
|
||||
|
||||
* Added thread latency/throughput performance examples.
|
||||
|
||||
* Added "--with-system-pgm" configure option to use already installed
|
||||
OpenPGM.
|
||||
|
||||
* Runtime checking of socket and context validity, to catch e.g. using a
|
||||
socket after closing it, or passing an invalid pointer to context/socket
|
||||
methods.
|
||||
|
||||
* Test cases moved off port 5555, which conflicts with other services.
|
||||
|
||||
* Clarified zmq_poll man page that the resolution of the timeout is 1msec.
|
||||
|
||||
|
||||
0MQ version 2.1.6 (Broken), released on 2011/04/26
|
||||
==================================================
|
||||
|
||||
Note that this version contained a malformed patch and is not usable.
|
||||
It is not available for download, but is available in the git via the
|
||||
2.1.6 tag.
|
||||
|
||||
0MQ version 2.1.5 (Broken), released on 2011/04/20
|
||||
==================================================
|
||||
|
||||
Note that this version contained a malformed patch and is not usable.
|
||||
It is not available for download, but is available in the git via the
|
||||
2.1.5 tag.
|
||||
|
||||
|
||||
0MQ version 2.1.4 (Stable), released on 2011/03/30
|
||||
==================================================
|
||||
|
||||
Bug fixes
|
||||
---------
|
||||
|
||||
* Fix to OpenPGM which was asserting on small messages (Steven McCoy).
|
||||
|
||||
Changes
|
||||
-------
|
||||
|
||||
* Upgraded OpenPGM to version 5.1.115 (Pieter Hintjens).
|
||||
|
||||
* OpenPGM build changed to not install OpenPGM artifacts.
|
||||
|
||||
|
||||
0MQ version 2.1.3 (Stable), released on 2011/03/21
|
||||
==================================================
|
||||
|
||||
Bug fixes
|
||||
---------
|
||||
|
||||
* Fix to PUSH sockets, which would sometimes deliver tail frames of a
|
||||
multipart message to new subscribers (Martin Sustrik).
|
||||
|
||||
* Fix to PUB sockets, which would sometimes deliver tail frames of a
|
||||
multipart message to new subscribers (Martin Sustrik).
|
||||
|
||||
* Windows build was broken due to EPROTONOSUPPORT not being defined. This
|
||||
has now been fixed (Martin Sustrik).
|
||||
|
||||
* Various fixes to make OpenVMS port work (Brett Cameron).
|
||||
|
||||
* Corrected Reference Manual to note that ZMQ_LINGER socket option may be
|
||||
set at any time, not just before connecting/binding (Pieter Hintjens).
|
||||
|
||||
* Fix to C++ binding to properly close sockets (Guido Goldstein).
|
||||
|
||||
* Removed obsolete assert from pgm_socket.cpp (Martin Sustrik).
|
||||
|
||||
Changes
|
||||
-------
|
||||
|
||||
* Removed stand-alone devices (/devices subdirectory) from distribution.
|
||||
These undocumented programs remain available in older packages (Pieter
|
||||
Hintjens).
|
||||
|
||||
* OpenPGM default rate raised to 40mbps by default (Steven McCoy).
|
||||
|
||||
* ZMQ_DEALER and ZMQ_ROUTER macros provided to ease upgrade to 0MQ/3.0.
|
||||
These are scheduled to replace ZMQ_XREQ and ZMQ_XREP (Pieter Hintjens).
|
||||
|
||||
* Added man page for zmq_device(3) which was hereto undocumented (Pieter
|
||||
Hintjens).
|
||||
|
||||
* Removed zmq_queue(3), zmq_forwarder(3), zmq_streamer(3) man pages
|
||||
(Pieter Hintjens).
|
||||
|
||||
OpenPGM Integration
|
||||
-------------------
|
||||
|
||||
* Upgraded OpenPGM to version 5.1.114 (Steven McCoy, Mikko Koppanen).
|
||||
|
||||
* Build system now calls OpenPGM build process directly, allowing easier
|
||||
future upgrades of OpenPGM (Mikko Koppanen).
|
||||
|
||||
* Build system allows configuration with arbitrary versions of OpenPGM
|
||||
(./configure --with-pgm=libpgm-x.y.z) (Mikko Koppanen).
|
||||
|
||||
* OpenPGM uses new PGM_ODATA_MAX_RTE controlling original data instead of
|
||||
PGM_TXW_MAX_RTE covering entire channel (Steven McCoy).
|
||||
|
||||
Building
|
||||
--------
|
||||
|
||||
* 0MQ builds properly on FreeBSD (Mikko Koppanen).
|
||||
|
||||
|
||||
0MQ version 2.1.2 (rc2), released on 2011/03/06
|
||||
===============================================
|
||||
|
||||
Bug fixes
|
||||
---------
|
||||
|
||||
* 0MQ now correctly handles durable inproc sockets; previously it ignored
|
||||
explicit identities on inproc sockets.
|
||||
|
||||
* Various memory leaks were fixed.
|
||||
|
||||
* OpenPGM sender/receiver creation fixed.
|
||||
|
||||
|
||||
0MQ version 2.1.1 (rc1), released on 2011/02/23
|
||||
===============================================
|
||||
|
||||
New functionality
|
||||
-----------------
|
||||
|
||||
* New socket option ZMQ_RECONNECT_IVL_MAX added, allows for exponential
|
||||
back-off strategy when reconnecting.
|
||||
|
||||
* New socket option ZMQ_RECOVERY_IVL_MSEC added, as a fine-grained
|
||||
counterpart to ZMQ_RECOVERY_IVL (for multicast transports).
|
||||
|
||||
* If memory is exhausted, 0MQ warns with an explicit message before
|
||||
aborting the process.
|
||||
|
||||
* Size of inproc HWM and SWAP is sum of peers' HWMs and SWAPs (Douglas
|
||||
Greager, Martin Sustrik).
|
||||
|
||||
Bug fixes
|
||||
---------
|
||||
|
||||
* 0MQ no longer asserts in mailbox.cpp when multiple peers connect with
|
||||
the same identity.
|
||||
|
||||
* 0MQ no longer asserts when rejecting an oversized message.
|
||||
|
||||
* 0MQ no longer asserts in pipe.cpp when the swap fills up.
|
||||
|
||||
* zmq_poll now works correctly with an empty poll set.
|
||||
|
||||
* Many more.
|
||||
|
||||
Building
|
||||
--------
|
||||
|
||||
* 0MQ now builds correctly on CentOS, Debian 6, and SunOS/gcc3.
|
||||
|
||||
* Added WithOpenPGM configuration into MSVC builds.
|
||||
|
||||
Known issues
|
||||
------------
|
||||
|
||||
* OpenPGM integration is still not fully stable.
|
||||
|
||||
|
||||
0MQ version 2.1.0 (Beta), released on 2010/12/01
|
||||
================================================
|
||||
|
||||
New functionality
|
||||
-----------------
|
||||
|
||||
* New semantics for zmq_close () and zmq_term () ensure that all messages
|
||||
are sent before the application terminates. This behaviour may be
|
||||
modified using the new ZMQ_LINGER socket option; for further details
|
||||
refer to the reference manual.
|
||||
|
||||
* The new socket options ZMQ_FD and ZMQ_EVENTS provide a way to integrate
|
||||
0MQ sockets into existing poll/event loops.
|
||||
|
||||
* Sockets may now be migrated between OS threads, as long as the
|
||||
application ensures that a full memory barrier is issued.
|
||||
|
||||
* The 0MQ ABI exported by libzmq.so has been formalised; DSO symbol
|
||||
visibility is used on supported platforms to ensure that only public ABI
|
||||
symbols are exported. The library ABI version has been set to 1.0.0 for
|
||||
this release.
|
||||
|
||||
* OpenPGM has been updated to version 5.0.92. This version no longer
|
||||
depends on GLIB, and integration with 0MQ should be much improved.
|
||||
|
||||
* zmq_poll() now honors timeouts precisely, and no longer returns if no
|
||||
events are signaled.
|
||||
|
||||
* Blocking calls now return EINTR if interrupted by the delivery of a
|
||||
signal; this also means that language bindings which previously had
|
||||
problems with handling SIGINT/^C should now work correctly.
|
||||
|
||||
* The ZMQ_TYPE socket option was added; this allows retrieval of the socket
|
||||
type after creation.
|
||||
|
||||
* Added a ZMQ_VERSION macro to zmq.h for compile-time API version
|
||||
detection.
|
||||
|
||||
* The ZMQ_RECONNECT_IVL and ZMQ_BACKLOG socket options have been added.
|
||||
|
||||
Bug fixes
|
||||
---------
|
||||
|
||||
* Forwarder and streamer devices now handle multi-part messages correctly.
|
||||
|
||||
* 0MQ no longer asserts when malformed data is received on the wire.
|
||||
|
||||
* 0MQ internal timers now work correctly if the TSC jumps backwards.
|
||||
|
||||
* The internal signalling functionality (mailbox) has been improved
|
||||
to automatically resize socket buffers on POSIX systems.
|
||||
|
||||
* Many more.
|
||||
|
||||
Building
|
||||
--------
|
||||
|
||||
* 0MQ now builds correctly with many more non-GCC compilers (Sun Studio,
|
||||
Intel ICC, CLang).
|
||||
|
||||
* AIX and HP-UX builds should work now.
|
||||
|
||||
* FD_SETSIZE has been set to 1024 by default for MSVC builds.
|
||||
|
||||
* Windows builds using GCC (MinGW) now work out of the box.
|
||||
|
||||
Distribution
|
||||
------------
|
||||
|
||||
* A simple framework for regression tests has been added, along with a few
|
||||
basic self-tests. The tests can be run using "make check".
|
||||
BIN
3rd/libzmq/branding.bmp
Normal file
BIN
3rd/libzmq/branding.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 25 KiB |
41
3rd/libzmq/builds/cmake/Modules/ClangFormat.cmake
Normal file
41
3rd/libzmq/builds/cmake/Modules/ClangFormat.cmake
Normal file
@@ -0,0 +1,41 @@
|
||||
# additional target to perform clang-format run, requires clang-format
|
||||
|
||||
# get all project files
|
||||
file(GLOB_RECURSE ALL_SOURCE_FILES
|
||||
RELATIVE ${CMAKE_CURRENT_BINARY_DIR}
|
||||
${CMAKE_SOURCE_DIR}/src/*.cpp ${CMAKE_SOURCE_DIR}/src/*.h ${CMAKE_SOURCE_DIR}/src/*.hpp
|
||||
${CMAKE_SOURCE_DIR}/tests/*.cpp ${CMAKE_SOURCE_DIR}/tests/*.h ${CMAKE_SOURCE_DIR}/tests/*.hpp
|
||||
${CMAKE_SOURCE_DIR}/perf/*.cpp ${CMAKE_SOURCE_DIR}/perf/*.h ${CMAKE_SOURCE_DIR}/perf/*.hpp
|
||||
${CMAKE_SOURCE_DIR}/tools/*.cpp ${CMAKE_SOURCE_DIR}/tools/*.h ${CMAKE_SOURCE_DIR}/tools/*.hpp
|
||||
${CMAKE_SOURCE_DIR}/include/*.h
|
||||
)
|
||||
|
||||
if("${CLANG_FORMAT}" STREQUAL "")
|
||||
set(CLANG_FORMAT "clang-format")
|
||||
endif()
|
||||
|
||||
add_custom_target(
|
||||
clang-format
|
||||
COMMAND ${CLANG_FORMAT} -style=file -i ${ALL_SOURCE_FILES}
|
||||
)
|
||||
|
||||
function(JOIN VALUES GLUE OUTPUT)
|
||||
string (REPLACE ";" "${GLUE}" _TMP_STR "${VALUES}")
|
||||
set (${OUTPUT} "${_TMP_STR}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
configure_file(builds/cmake/clang-format-check.sh.in clang-format-check.sh @ONLY)
|
||||
|
||||
add_custom_target(
|
||||
clang-format-check
|
||||
COMMAND chmod +x clang-format-check.sh
|
||||
COMMAND ./clang-format-check.sh
|
||||
COMMENT "Checking correct formatting according to .clang-format file using ${CLANG_FORMAT}"
|
||||
)
|
||||
|
||||
add_custom_target(
|
||||
clang-format-diff
|
||||
COMMAND ${CLANG_FORMAT} -style=file -i ${ALL_SOURCE_FILES}
|
||||
COMMAND git diff ${ALL_SOURCE_FILES}
|
||||
COMMENT "Formatting with clang-format (using ${CLANG_FORMAT}) and showing differences with latest commit"
|
||||
)
|
||||
26
3rd/libzmq/builds/cmake/Modules/FindAsciiDoc.cmake
Normal file
26
3rd/libzmq/builds/cmake/Modules/FindAsciiDoc.cmake
Normal file
@@ -0,0 +1,26 @@
|
||||
# - Find Asciidoc
|
||||
# this module looks for asciidoc and a2x
|
||||
#
|
||||
# ASCIIDOC_EXECUTABLE - the full path to asciidoc
|
||||
# ASCIIDOC_FOUND - If false, don't attempt to use asciidoc.
|
||||
# A2X_EXECUTABLE - the full path to a2x
|
||||
# A2X_FOUND - If false, don't attempt to use a2x.
|
||||
|
||||
set (PROGRAMFILESX86 "PROGRAMFILES(X86)")
|
||||
|
||||
find_program(ASCIIDOC_EXECUTABLE asciidoc asciidoc.py
|
||||
PATHS "$ENV{ASCIIDOC_ROOT}"
|
||||
"$ENV{PROGRAMW6432}/asciidoc"
|
||||
"$ENV{PROGRAMFILES}/asciidoc"
|
||||
"$ENV{${PROGRAMFILESX86}}/asciidoc")
|
||||
|
||||
find_program(A2X_EXECUTABLE a2x
|
||||
PATHS "$ENV{ASCIIDOC_ROOT}"
|
||||
"$ENV{PROGRAMW6432}/asciidoc"
|
||||
"$ENV{PROGRAMFILES}/asciidoc"
|
||||
"$ENV{${PROGRAMFILESX86}}/asciidoc")
|
||||
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_ARGS(AsciiDoc REQUIRED_VARS ASCIIDOC_EXECUTABLE)
|
||||
mark_as_advanced(ASCIIDOC_EXECUTABLE A2X_EXECUTABLE)
|
||||
8
3rd/libzmq/builds/cmake/Modules/FindNSS3.cmake
Normal file
8
3rd/libzmq/builds/cmake/Modules/FindNSS3.cmake
Normal file
@@ -0,0 +1,8 @@
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
if (NOT MSVC)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(NSS3 "nss>=3.19")
|
||||
find_package_handle_standard_args(NSS3 DEFAULT_MSG NSS3_LIBRARIES NSS3_CFLAGS)
|
||||
endif()
|
||||
|
||||
48
3rd/libzmq/builds/cmake/Modules/FindSodium.cmake
Normal file
48
3rd/libzmq/builds/cmake/Modules/FindSodium.cmake
Normal file
@@ -0,0 +1,48 @@
|
||||
################################################################################
|
||||
# THIS FILE IS 100% GENERATED BY ZPROJECT; DO NOT EDIT EXCEPT EXPERIMENTALLY #
|
||||
# Please refer to the README for information about making permanent changes. #
|
||||
################################################################################
|
||||
|
||||
if (NOT MSVC)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(PC_SODIUM "libsodium")
|
||||
if (PC_SODIUM_FOUND)
|
||||
set(pkg_config_names_private "${pkg_config_names_private} libsodium")
|
||||
endif()
|
||||
if (NOT PC_SODIUM_FOUND)
|
||||
pkg_check_modules(PC_SODIUM "sodium")
|
||||
if (PC_SODIUM_FOUND)
|
||||
set(pkg_config_names_private "${pkg_config_names_private} sodium")
|
||||
endif()
|
||||
endif (NOT PC_SODIUM_FOUND)
|
||||
if (PC_SODIUM_FOUND)
|
||||
set(SODIUM_INCLUDE_HINTS ${PC_SODIUM_INCLUDE_DIRS} ${PC_SODIUM_INCLUDE_DIRS}/*)
|
||||
set(SODIUM_LIBRARY_HINTS ${PC_SODIUM_LIBRARY_DIRS} ${PC_SODIUM_LIBRARY_DIRS}/*)
|
||||
else()
|
||||
set(pkg_config_libs_private "${pkg_config_libs_private} -lsodium")
|
||||
endif()
|
||||
endif (NOT MSVC)
|
||||
|
||||
# some libraries install the headers is a subdirectory of the include dir
|
||||
# returned by pkg-config, so use a wildcard match to improve chances of finding
|
||||
# headers and libraries.
|
||||
find_path(
|
||||
SODIUM_INCLUDE_DIRS
|
||||
NAMES sodium.h
|
||||
HINTS ${SODIUM_INCLUDE_HINTS}
|
||||
)
|
||||
|
||||
find_library(
|
||||
SODIUM_LIBRARIES
|
||||
NAMES libsodium sodium
|
||||
HINTS ${SODIUM_LIBRARY_HINTS}
|
||||
)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(sodium DEFAULT_MSG SODIUM_LIBRARIES SODIUM_INCLUDE_DIRS)
|
||||
mark_as_advanced(SODIUM_FOUND SODIUM_LIBRARIES SODIUM_INCLUDE_DIRS)
|
||||
|
||||
################################################################################
|
||||
# THIS FILE IS 100% GENERATED BY ZPROJECT; DO NOT EDIT EXCEPT EXPERIMENTALLY #
|
||||
# Please refer to the README for information about making permanent changes. #
|
||||
################################################################################
|
||||
8
3rd/libzmq/builds/cmake/Modules/TestZMQVersion.cmake
Normal file
8
3rd/libzmq/builds/cmake/Modules/TestZMQVersion.cmake
Normal file
@@ -0,0 +1,8 @@
|
||||
|
||||
file(READ "${PROJECT_SOURCE_DIR}/include/zmq.h" _ZMQ_H_CONTENTS)
|
||||
string(REGEX REPLACE ".*#define ZMQ_VERSION_MAJOR ([0-9]+).*" "\\1" ZMQ_VERSION_MAJOR "${_ZMQ_H_CONTENTS}")
|
||||
string(REGEX REPLACE ".*#define ZMQ_VERSION_MINOR ([0-9]+).*" "\\1" ZMQ_VERSION_MINOR "${_ZMQ_H_CONTENTS}")
|
||||
string(REGEX REPLACE ".*#define ZMQ_VERSION_PATCH ([0-9]+).*" "\\1" ZMQ_VERSION_PATCH "${_ZMQ_H_CONTENTS}")
|
||||
set(ZMQ_VERSION "${ZMQ_VERSION_MAJOR}.${ZMQ_VERSION_MINOR}.${ZMQ_VERSION_PATCH}")
|
||||
|
||||
message(STATUS "Detected ZMQ Version - ${ZMQ_VERSION}")
|
||||
332
3rd/libzmq/builds/cmake/Modules/ZMQSourceRunChecks.cmake
Normal file
332
3rd/libzmq/builds/cmake/Modules/ZMQSourceRunChecks.cmake
Normal file
@@ -0,0 +1,332 @@
|
||||
|
||||
|
||||
macro(zmq_check_sock_cloexec)
|
||||
message(STATUS "Checking whether SOCK_CLOEXEC is supported")
|
||||
check_c_source_runs(
|
||||
"
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
int main(int argc, char *argv [])
|
||||
{
|
||||
int s = socket(PF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
|
||||
return(s == -1);
|
||||
}
|
||||
"
|
||||
ZMQ_HAVE_SOCK_CLOEXEC)
|
||||
endmacro()
|
||||
|
||||
macro(zmq_check_efd_cloexec)
|
||||
message(STATUS "Checking whether EFD_CLOEXEC is supported")
|
||||
check_c_source_runs(
|
||||
"
|
||||
#include <sys/eventfd.h>
|
||||
|
||||
int main(int argc, char *argv [])
|
||||
{
|
||||
int s = eventfd (0, EFD_CLOEXEC);
|
||||
return(s == -1);
|
||||
}
|
||||
"
|
||||
ZMQ_HAVE_EVENTFD_CLOEXEC)
|
||||
endmacro()
|
||||
|
||||
macro(zmq_check_o_cloexec)
|
||||
message(STATUS "Checking whether O_CLOEXEC is supported")
|
||||
check_c_source_runs(
|
||||
"
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
int main(int argc, char *argv [])
|
||||
{
|
||||
int s = open (\"/dev/null\", O_CLOEXEC | O_RDONLY);
|
||||
return s == -1;
|
||||
}
|
||||
"
|
||||
ZMQ_HAVE_O_CLOEXEC)
|
||||
endmacro()
|
||||
|
||||
macro(zmq_check_so_bindtodevice)
|
||||
message(STATUS "Checking whether SO_BINDTODEVICE is supported")
|
||||
check_c_source_runs(
|
||||
"
|
||||
#include <sys/socket.h>
|
||||
|
||||
int main(int argc, char *argv [])
|
||||
{
|
||||
/* Actually making the setsockopt() call requires CAP_NET_RAW */
|
||||
#ifndef SO_BINDTODEVICE
|
||||
return 1;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
"
|
||||
ZMQ_HAVE_SO_BINDTODEVICE)
|
||||
endmacro()
|
||||
|
||||
# TCP keep-alives Checks.
|
||||
|
||||
macro(zmq_check_so_keepalive)
|
||||
message(STATUS "Checking whether SO_KEEPALIVE is supported")
|
||||
check_c_source_runs(
|
||||
"
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
int main(int argc, char *argv [])
|
||||
{
|
||||
int s, rc, opt = 1;
|
||||
return(
|
||||
((s = socket(PF_INET, SOCK_STREAM, 0)) == -1) ||
|
||||
((rc = setsockopt(s, SOL_SOCKET, SO_KEEPALIVE,(char*) &opt, sizeof(int))) == -1)
|
||||
);
|
||||
}
|
||||
"
|
||||
ZMQ_HAVE_SO_KEEPALIVE)
|
||||
endmacro()
|
||||
|
||||
macro(zmq_check_tcp_keepcnt)
|
||||
message(STATUS "Checking whether TCP_KEEPCNT is supported")
|
||||
check_c_source_runs(
|
||||
"
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
int main(int argc, char *argv [])
|
||||
{
|
||||
int s, rc, opt = 1;
|
||||
return(
|
||||
((s = socket(PF_INET, SOCK_STREAM, 0)) == -1) ||
|
||||
((rc = setsockopt(s, SOL_SOCKET, SO_KEEPALIVE,(char*) &opt, sizeof(int))) == -1) ||
|
||||
((rc = setsockopt(s, IPPROTO_TCP, TCP_KEEPCNT,(char*) &opt, sizeof(int))) == -1)
|
||||
);
|
||||
}
|
||||
"
|
||||
ZMQ_HAVE_TCP_KEEPCNT)
|
||||
endmacro()
|
||||
|
||||
macro(zmq_check_tcp_keepidle)
|
||||
message(STATUS "Checking whether TCP_KEEPIDLE is supported")
|
||||
check_c_source_runs(
|
||||
"
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
int main(int argc, char *argv [])
|
||||
{
|
||||
int s, rc, opt = 1;
|
||||
return(
|
||||
((s = socket(PF_INET, SOCK_STREAM, 0)) == -1) ||
|
||||
((rc = setsockopt(s, SOL_SOCKET, SO_KEEPALIVE,(char*) &opt, sizeof(int))) == -1) ||
|
||||
((rc = setsockopt(s, IPPROTO_TCP, TCP_KEEPIDLE,(char*) &opt, sizeof(int))) == -1)
|
||||
);
|
||||
}
|
||||
"
|
||||
ZMQ_HAVE_TCP_KEEPIDLE)
|
||||
endmacro()
|
||||
|
||||
|
||||
macro(zmq_check_tcp_keepintvl)
|
||||
message(STATUS "Checking whether TCP_KEEPINTVL is supported")
|
||||
check_c_source_runs(
|
||||
"
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
int main(int argc, char *argv [])
|
||||
{
|
||||
int s, rc, opt = 1;
|
||||
return(
|
||||
((s = socket(PF_INET, SOCK_STREAM, 0)) == -1) ||
|
||||
((rc = setsockopt(s, SOL_SOCKET, SO_KEEPALIVE,(char*) &opt, sizeof(int))) == -1) ||
|
||||
((rc = setsockopt(s, IPPROTO_TCP, TCP_KEEPINTVL,(char*) &opt, sizeof(int))) == -1)
|
||||
);
|
||||
}
|
||||
|
||||
"
|
||||
ZMQ_HAVE_TCP_KEEPINTVL)
|
||||
endmacro()
|
||||
|
||||
|
||||
macro(zmq_check_tcp_keepalive)
|
||||
message(STATUS "Checking whether TCP_KEEPALIVE is supported")
|
||||
check_c_source_runs(
|
||||
"
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
int main(int argc, char *argv [])
|
||||
{
|
||||
int s, rc, opt = 1;
|
||||
return(
|
||||
((s = socket(PF_INET, SOCK_STREAM, 0)) == -1) ||
|
||||
((rc = setsockopt(s, SOL_SOCKET, SO_KEEPALIVE,(char*) &opt, sizeof(int))) == -1) ||
|
||||
((rc = setsockopt(s, IPPROTO_TCP, TCP_KEEPALIVE,(char*) &opt, sizeof(int))) == -1)
|
||||
);
|
||||
}
|
||||
"
|
||||
ZMQ_HAVE_TCP_KEEPALIVE)
|
||||
endmacro()
|
||||
|
||||
|
||||
macro(zmq_check_tcp_tipc)
|
||||
message(STATUS "Checking whether TIPC is supported")
|
||||
check_c_source_runs(
|
||||
"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <sys/socket.h>
|
||||
#include <linux/tipc.h>
|
||||
|
||||
int main(int argc, char *argv [])
|
||||
{
|
||||
struct sockaddr_tipc topsrv;
|
||||
int sd = socket(AF_TIPC, SOCK_SEQPACKET, 0);
|
||||
memset(&topsrv, 0, sizeof(topsrv));
|
||||
topsrv.family = AF_TIPC;
|
||||
topsrv.addrtype = TIPC_ADDR_NAME;
|
||||
topsrv.addr.name.name.type = TIPC_TOP_SRV;
|
||||
topsrv.addr.name.name.instance = TIPC_TOP_SRV;
|
||||
fcntl(sd, F_SETFL, O_NONBLOCK);
|
||||
}
|
||||
"
|
||||
ZMQ_HAVE_TIPC)
|
||||
endmacro()
|
||||
|
||||
|
||||
macro(zmq_check_pthread_setname)
|
||||
message(STATUS "Checking pthread_setname signature")
|
||||
set(SAVE_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
|
||||
set(CMAKE_REQUIRED_FLAGS "-D_GNU_SOURCE -Werror -pthread")
|
||||
check_c_source_runs(
|
||||
"
|
||||
#include <pthread.h>
|
||||
|
||||
int main(int argc, char *argv [])
|
||||
{
|
||||
pthread_setname_np (\"foo\");
|
||||
return 0;
|
||||
}
|
||||
"
|
||||
ZMQ_HAVE_PTHREAD_SETNAME_1)
|
||||
check_c_source_runs(
|
||||
"
|
||||
#include <pthread.h>
|
||||
|
||||
int main(int argc, char *argv [])
|
||||
{
|
||||
pthread_setname_np (pthread_self(), \"foo\");
|
||||
return 0;
|
||||
}
|
||||
"
|
||||
ZMQ_HAVE_PTHREAD_SETNAME_2)
|
||||
check_c_source_runs(
|
||||
"
|
||||
#include <pthread.h>
|
||||
|
||||
int main(int argc, char *argv [])
|
||||
{
|
||||
pthread_setname_np (pthread_self(), \"foo\", (void *)0);
|
||||
return 0;
|
||||
}
|
||||
"
|
||||
ZMQ_HAVE_PTHREAD_SETNAME_3)
|
||||
check_c_source_runs(
|
||||
"
|
||||
#include <pthread.h>
|
||||
|
||||
int main(int argc, char *argv [])
|
||||
{
|
||||
pthread_set_name_np (pthread_self(), \"foo\");
|
||||
return 0;
|
||||
}
|
||||
"
|
||||
ZMQ_HAVE_PTHREAD_SET_NAME)
|
||||
set(CMAKE_REQUIRED_FLAGS ${SAVE_CMAKE_REQUIRED_FLAGS})
|
||||
endmacro()
|
||||
|
||||
macro(zmq_check_pthread_setaffinity)
|
||||
message(STATUS "Checking pthread_setaffinity signature")
|
||||
set(SAVE_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
|
||||
set(CMAKE_REQUIRED_FLAGS "-D_GNU_SOURCE -Werror -pthread")
|
||||
check_c_source_runs(
|
||||
"
|
||||
#include <pthread.h>
|
||||
|
||||
int main(int argc, char *argv [])
|
||||
{
|
||||
cpu_set_t test;
|
||||
pthread_setaffinity_np (pthread_self(), sizeof(cpu_set_t), &test);
|
||||
return 0;
|
||||
}
|
||||
"
|
||||
ZMQ_HAVE_PTHREAD_SET_AFFINITY)
|
||||
set(CMAKE_REQUIRED_FLAGS ${SAVE_CMAKE_REQUIRED_FLAGS})
|
||||
endmacro()
|
||||
|
||||
|
||||
macro(zmq_check_getrandom)
|
||||
message(STATUS "Checking whether getrandom is supported")
|
||||
check_c_source_runs(
|
||||
"
|
||||
#include <sys/random.h>
|
||||
|
||||
int main (int argc, char *argv [])
|
||||
{
|
||||
char buf[4];
|
||||
int rc = getrandom(buf, 4, 0);
|
||||
return rc == -1 ? 1 : 0;
|
||||
}
|
||||
"
|
||||
ZMQ_HAVE_GETRANDOM)
|
||||
endmacro()
|
||||
|
||||
macro(zmq_check_noexcept)
|
||||
message(STATUS "Checking whether noexcept is supported")
|
||||
check_cxx_source_compiles(
|
||||
"
|
||||
struct X
|
||||
{
|
||||
X(int i) noexcept {}
|
||||
};
|
||||
|
||||
int main(int argc, char *argv [])
|
||||
{
|
||||
X x(5);
|
||||
return 0;
|
||||
}
|
||||
"
|
||||
ZMQ_HAVE_NOEXCEPT)
|
||||
endmacro()
|
||||
|
||||
macro(zmq_check_so_priority)
|
||||
message(STATUS "Checking whether SO_PRIORITY is supported")
|
||||
check_c_source_runs(
|
||||
"
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
int main (int argc, char *argv [])
|
||||
{
|
||||
int s, rc, opt = 1;
|
||||
return (
|
||||
((s = socket (PF_INET, SOCK_STREAM, 0)) == -1) ||
|
||||
((rc = setsockopt (s, SOL_SOCKET, SO_PRIORITY, (char*) &opt, sizeof (int))) == -1)
|
||||
);
|
||||
}
|
||||
"
|
||||
ZMQ_HAVE_SO_PRIORITY)
|
||||
endmacro()
|
||||
5
3rd/libzmq/builds/cmake/Modules/ZMQSupportMacros.cmake
Normal file
5
3rd/libzmq/builds/cmake/Modules/ZMQSupportMacros.cmake
Normal file
@@ -0,0 +1,5 @@
|
||||
macro (zmq_set_with_default var value)
|
||||
if (NOT ${var})
|
||||
set(${var} "${value}")
|
||||
endif ()
|
||||
endmacro ()
|
||||
952
3rd/libzmq/builds/cmake/NSIS.template32.in
Normal file
952
3rd/libzmq/builds/cmake/NSIS.template32.in
Normal file
@@ -0,0 +1,952 @@
|
||||
; CPack install script designed for a nmake build
|
||||
|
||||
;--------------------------------
|
||||
; You must define these values
|
||||
|
||||
!define VERSION "@CPACK_PACKAGE_VERSION@"
|
||||
!define PATCH "@CPACK_PACKAGE_VERSION_PATCH@"
|
||||
!define INST_DIR "@CPACK_TEMPORARY_DIRECTORY@"
|
||||
|
||||
;--------------------------------
|
||||
;Variables
|
||||
|
||||
Var MUI_TEMP
|
||||
Var STARTMENU_FOLDER
|
||||
Var SV_ALLUSERS
|
||||
Var START_MENU
|
||||
Var DO_NOT_ADD_TO_PATH
|
||||
Var ADD_TO_PATH_ALL_USERS
|
||||
Var ADD_TO_PATH_CURRENT_USER
|
||||
Var INSTALL_DESKTOP
|
||||
Var IS_DEFAULT_INSTALLDIR
|
||||
;--------------------------------
|
||||
;Include Modern UI
|
||||
|
||||
!include "MUI.nsh"
|
||||
|
||||
;Default installation folder
|
||||
InstallDir "$PROGRAMFILES\@CPACK_PACKAGE_INSTALL_DIRECTORY@"
|
||||
;InstallDir "$PROGRAMFILES64\@CPACK_PACKAGE_INSTALL_DIRECTORY@"
|
||||
|
||||
;--------------------------------
|
||||
;General
|
||||
|
||||
;Name and file
|
||||
Name "@CPACK_NSIS_PACKAGE_NAME@"
|
||||
OutFile "@CPACK_TOPLEVEL_DIRECTORY@/@CPACK_OUTPUT_FILE_NAME@"
|
||||
|
||||
;Set compression
|
||||
SetCompressor @CPACK_NSIS_COMPRESSOR@
|
||||
|
||||
@CPACK_NSIS_DEFINES@
|
||||
|
||||
!include Sections.nsh
|
||||
|
||||
;--- Component support macros: ---
|
||||
; The code for the add/remove functionality is from:
|
||||
; http://nsis.sourceforge.net/Add/Remove_Functionality
|
||||
; It has been modified slightly and extended to provide
|
||||
; inter-component dependencies.
|
||||
Var AR_SecFlags
|
||||
Var AR_RegFlags
|
||||
@CPACK_NSIS_SECTION_SELECTED_VARS@
|
||||
|
||||
; Loads the "selected" flag for the section named SecName into the
|
||||
; variable VarName.
|
||||
!macro LoadSectionSelectedIntoVar SecName VarName
|
||||
SectionGetFlags ${${SecName}} $${VarName}
|
||||
IntOp $${VarName} $${VarName} & ${SF_SELECTED} ;Turn off all other bits
|
||||
!macroend
|
||||
|
||||
; Loads the value of a variable... can we get around this?
|
||||
!macro LoadVar VarName
|
||||
IntOp $R0 0 + $${VarName}
|
||||
!macroend
|
||||
|
||||
; Sets the value of a variable
|
||||
!macro StoreVar VarName IntValue
|
||||
IntOp $${VarName} 0 + ${IntValue}
|
||||
!macroend
|
||||
|
||||
!macro InitSection SecName
|
||||
; This macro reads component installed flag from the registry and
|
||||
;changes checked state of the section on the components page.
|
||||
;Input: section index constant name specified in Section command.
|
||||
|
||||
ClearErrors
|
||||
;Reading component status from registry
|
||||
ReadRegDWORD $AR_RegFlags HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@\Components\${SecName}" "Installed"
|
||||
IfErrors "default_${SecName}"
|
||||
;Status will stay default if registry value not found
|
||||
;(component was never installed)
|
||||
IntOp $AR_RegFlags $AR_RegFlags & ${SF_SELECTED} ;Turn off all other bits
|
||||
SectionGetFlags ${${SecName}} $AR_SecFlags ;Reading default section flags
|
||||
IntOp $AR_SecFlags $AR_SecFlags & 0xFFFE ;Turn lowest (enabled) bit off
|
||||
IntOp $AR_SecFlags $AR_RegFlags | $AR_SecFlags ;Change lowest bit
|
||||
|
||||
; Note whether this component was installed before
|
||||
!insertmacro StoreVar ${SecName}_was_installed $AR_RegFlags
|
||||
IntOp $R0 $AR_RegFlags & $AR_RegFlags
|
||||
|
||||
;Writing modified flags
|
||||
SectionSetFlags ${${SecName}} $AR_SecFlags
|
||||
|
||||
"default_${SecName}:"
|
||||
!insertmacro LoadSectionSelectedIntoVar ${SecName} ${SecName}_selected
|
||||
!macroend
|
||||
|
||||
!macro FinishSection SecName
|
||||
; This macro reads section flag set by user and removes the section
|
||||
;if it is not selected.
|
||||
;Then it writes component installed flag to registry
|
||||
;Input: section index constant name specified in Section command.
|
||||
|
||||
SectionGetFlags ${${SecName}} $AR_SecFlags ;Reading section flags
|
||||
;Checking lowest bit:
|
||||
IntOp $AR_SecFlags $AR_SecFlags & ${SF_SELECTED}
|
||||
IntCmp $AR_SecFlags 1 "leave_${SecName}"
|
||||
;Section is not selected:
|
||||
;Calling Section uninstall macro and writing zero installed flag
|
||||
!insertmacro "Remove_${${SecName}}"
|
||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@\Components\${SecName}" \
|
||||
"Installed" 0
|
||||
Goto "exit_${SecName}"
|
||||
|
||||
"leave_${SecName}:"
|
||||
;Section is selected:
|
||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@\Components\${SecName}" \
|
||||
"Installed" 1
|
||||
|
||||
"exit_${SecName}:"
|
||||
!macroend
|
||||
|
||||
!macro RemoveSection SecName
|
||||
; This macro is used to call section's Remove_... macro
|
||||
;from the uninstaller.
|
||||
;Input: section index constant name specified in Section command.
|
||||
|
||||
!insertmacro "Remove_${${SecName}}"
|
||||
!macroend
|
||||
|
||||
; Determine whether the selection of SecName changed
|
||||
!macro MaybeSelectionChanged SecName
|
||||
!insertmacro LoadVar ${SecName}_selected
|
||||
SectionGetFlags ${${SecName}} $R1
|
||||
IntOp $R1 $R1 & ${SF_SELECTED} ;Turn off all other bits
|
||||
|
||||
; See if the status has changed:
|
||||
IntCmp $R0 $R1 "${SecName}_unchanged"
|
||||
!insertmacro LoadSectionSelectedIntoVar ${SecName} ${SecName}_selected
|
||||
|
||||
IntCmp $R1 ${SF_SELECTED} "${SecName}_was_selected"
|
||||
!insertmacro "Deselect_required_by_${SecName}"
|
||||
goto "${SecName}_unchanged"
|
||||
|
||||
"${SecName}_was_selected:"
|
||||
!insertmacro "Select_${SecName}_depends"
|
||||
|
||||
"${SecName}_unchanged:"
|
||||
!macroend
|
||||
;--- End of Add/Remove macros ---
|
||||
|
||||
;--------------------------------
|
||||
;Interface Settings
|
||||
|
||||
!define MUI_HEADERIMAGE
|
||||
!define MUI_ABORTWARNING
|
||||
|
||||
;--------------------------------
|
||||
; path functions
|
||||
|
||||
!verbose 3
|
||||
!include "WinMessages.NSH"
|
||||
!verbose 4
|
||||
|
||||
;----------------------------------------
|
||||
; based upon a script of "Written by KiCHiK 2003-01-18 05:57:02"
|
||||
;----------------------------------------
|
||||
!verbose 3
|
||||
!include "WinMessages.NSH"
|
||||
!verbose 4
|
||||
;====================================================
|
||||
; get_NT_environment
|
||||
; Returns: the selected environment
|
||||
; Output : head of the stack
|
||||
;====================================================
|
||||
!macro select_NT_profile UN
|
||||
Function ${UN}select_NT_profile
|
||||
StrCmp $ADD_TO_PATH_ALL_USERS "1" 0 environment_single
|
||||
DetailPrint "Selected environment for all users"
|
||||
Push "all"
|
||||
Return
|
||||
environment_single:
|
||||
DetailPrint "Selected environment for current user only."
|
||||
Push "current"
|
||||
Return
|
||||
FunctionEnd
|
||||
!macroend
|
||||
!insertmacro select_NT_profile ""
|
||||
!insertmacro select_NT_profile "un."
|
||||
;----------------------------------------------------
|
||||
!define NT_current_env 'HKCU "Environment"'
|
||||
!define NT_all_env 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"'
|
||||
|
||||
!ifndef WriteEnvStr_RegKey
|
||||
!ifdef ALL_USERS
|
||||
!define WriteEnvStr_RegKey \
|
||||
'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"'
|
||||
!else
|
||||
!define WriteEnvStr_RegKey 'HKCU "Environment"'
|
||||
!endif
|
||||
!endif
|
||||
|
||||
; AddToPath - Adds the given dir to the search path.
|
||||
; Input - head of the stack
|
||||
; Note - Win9x systems requires reboot
|
||||
|
||||
Function AddToPath
|
||||
Exch $0
|
||||
Push $1
|
||||
Push $2
|
||||
Push $3
|
||||
|
||||
# don't add if the path doesn't exist
|
||||
IfFileExists "$0\*.*" "" AddToPath_done
|
||||
|
||||
ReadEnvStr $1 PATH
|
||||
; if the path is too long for a NSIS variable NSIS will return a 0
|
||||
; length string. If we find that, then warn and skip any path
|
||||
; modification as it will trash the existing path.
|
||||
StrLen $2 $1
|
||||
IntCmp $2 0 CheckPathLength_ShowPathWarning CheckPathLength_Done CheckPathLength_Done
|
||||
CheckPathLength_ShowPathWarning:
|
||||
Messagebox MB_OK|MB_ICONEXCLAMATION "Warning! PATH too long installer unable to modify PATH!"
|
||||
Goto AddToPath_done
|
||||
CheckPathLength_Done:
|
||||
Push "$1;"
|
||||
Push "$0;"
|
||||
Call StrStr
|
||||
Pop $2
|
||||
StrCmp $2 "" "" AddToPath_done
|
||||
Push "$1;"
|
||||
Push "$0\;"
|
||||
Call StrStr
|
||||
Pop $2
|
||||
StrCmp $2 "" "" AddToPath_done
|
||||
GetFullPathName /SHORT $3 $0
|
||||
Push "$1;"
|
||||
Push "$3;"
|
||||
Call StrStr
|
||||
Pop $2
|
||||
StrCmp $2 "" "" AddToPath_done
|
||||
Push "$1;"
|
||||
Push "$3\;"
|
||||
Call StrStr
|
||||
Pop $2
|
||||
StrCmp $2 "" "" AddToPath_done
|
||||
|
||||
Call IsNT
|
||||
Pop $1
|
||||
StrCmp $1 1 AddToPath_NT
|
||||
; Not on NT
|
||||
StrCpy $1 $WINDIR 2
|
||||
FileOpen $1 "$1\autoexec.bat" a
|
||||
FileSeek $1 -1 END
|
||||
FileReadByte $1 $2
|
||||
IntCmp $2 26 0 +2 +2 # DOS EOF
|
||||
FileSeek $1 -1 END # write over EOF
|
||||
FileWrite $1 "$\r$\nSET PATH=%PATH%;$3$\r$\n"
|
||||
FileClose $1
|
||||
SetRebootFlag true
|
||||
Goto AddToPath_done
|
||||
|
||||
AddToPath_NT:
|
||||
StrCmp $ADD_TO_PATH_ALL_USERS "1" ReadAllKey
|
||||
ReadRegStr $1 ${NT_current_env} "PATH"
|
||||
Goto DoTrim
|
||||
ReadAllKey:
|
||||
ReadRegStr $1 ${NT_all_env} "PATH"
|
||||
DoTrim:
|
||||
StrCmp $1 "" AddToPath_NTdoIt
|
||||
Push $1
|
||||
Call Trim
|
||||
Pop $1
|
||||
StrCpy $0 "$1;$0"
|
||||
AddToPath_NTdoIt:
|
||||
StrCmp $ADD_TO_PATH_ALL_USERS "1" WriteAllKey
|
||||
WriteRegExpandStr ${NT_current_env} "PATH" $0
|
||||
Goto DoSend
|
||||
WriteAllKey:
|
||||
WriteRegExpandStr ${NT_all_env} "PATH" $0
|
||||
DoSend:
|
||||
SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
|
||||
|
||||
AddToPath_done:
|
||||
Pop $3
|
||||
Pop $2
|
||||
Pop $1
|
||||
Pop $0
|
||||
FunctionEnd
|
||||
|
||||
|
||||
; RemoveFromPath - Remove a given dir from the path
|
||||
; Input: head of the stack
|
||||
|
||||
Function un.RemoveFromPath
|
||||
Exch $0
|
||||
Push $1
|
||||
Push $2
|
||||
Push $3
|
||||
Push $4
|
||||
Push $5
|
||||
Push $6
|
||||
|
||||
IntFmt $6 "%c" 26 # DOS EOF
|
||||
|
||||
Call un.IsNT
|
||||
Pop $1
|
||||
StrCmp $1 1 unRemoveFromPath_NT
|
||||
; Not on NT
|
||||
StrCpy $1 $WINDIR 2
|
||||
FileOpen $1 "$1\autoexec.bat" r
|
||||
GetTempFileName $4
|
||||
FileOpen $2 $4 w
|
||||
GetFullPathName /SHORT $0 $0
|
||||
StrCpy $0 "SET PATH=%PATH%;$0"
|
||||
Goto unRemoveFromPath_dosLoop
|
||||
|
||||
unRemoveFromPath_dosLoop:
|
||||
FileRead $1 $3
|
||||
StrCpy $5 $3 1 -1 # read last char
|
||||
StrCmp $5 $6 0 +2 # if DOS EOF
|
||||
StrCpy $3 $3 -1 # remove DOS EOF so we can compare
|
||||
StrCmp $3 "$0$\r$\n" unRemoveFromPath_dosLoopRemoveLine
|
||||
StrCmp $3 "$0$\n" unRemoveFromPath_dosLoopRemoveLine
|
||||
StrCmp $3 "$0" unRemoveFromPath_dosLoopRemoveLine
|
||||
StrCmp $3 "" unRemoveFromPath_dosLoopEnd
|
||||
FileWrite $2 $3
|
||||
Goto unRemoveFromPath_dosLoop
|
||||
unRemoveFromPath_dosLoopRemoveLine:
|
||||
SetRebootFlag true
|
||||
Goto unRemoveFromPath_dosLoop
|
||||
|
||||
unRemoveFromPath_dosLoopEnd:
|
||||
FileClose $2
|
||||
FileClose $1
|
||||
StrCpy $1 $WINDIR 2
|
||||
Delete "$1\autoexec.bat"
|
||||
CopyFiles /SILENT $4 "$1\autoexec.bat"
|
||||
Delete $4
|
||||
Goto unRemoveFromPath_done
|
||||
|
||||
unRemoveFromPath_NT:
|
||||
StrCmp $ADD_TO_PATH_ALL_USERS "1" unReadAllKey
|
||||
ReadRegStr $1 ${NT_current_env} "PATH"
|
||||
Goto unDoTrim
|
||||
unReadAllKey:
|
||||
ReadRegStr $1 ${NT_all_env} "PATH"
|
||||
unDoTrim:
|
||||
StrCpy $5 $1 1 -1 # copy last char
|
||||
StrCmp $5 ";" +2 # if last char != ;
|
||||
StrCpy $1 "$1;" # append ;
|
||||
Push $1
|
||||
Push "$0;"
|
||||
Call un.StrStr ; Find `$0;` in $1
|
||||
Pop $2 ; pos of our dir
|
||||
StrCmp $2 "" unRemoveFromPath_done
|
||||
; else, it is in path
|
||||
# $0 - path to add
|
||||
# $1 - path var
|
||||
StrLen $3 "$0;"
|
||||
StrLen $4 $2
|
||||
StrCpy $5 $1 -$4 # $5 is now the part before the path to remove
|
||||
StrCpy $6 $2 "" $3 # $6 is now the part after the path to remove
|
||||
StrCpy $3 $5$6
|
||||
|
||||
StrCpy $5 $3 1 -1 # copy last char
|
||||
StrCmp $5 ";" 0 +2 # if last char == ;
|
||||
StrCpy $3 $3 -1 # remove last char
|
||||
|
||||
StrCmp $ADD_TO_PATH_ALL_USERS "1" unWriteAllKey
|
||||
WriteRegExpandStr ${NT_current_env} "PATH" $3
|
||||
Goto unDoSend
|
||||
unWriteAllKey:
|
||||
WriteRegExpandStr ${NT_all_env} "PATH" $3
|
||||
unDoSend:
|
||||
SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
|
||||
|
||||
unRemoveFromPath_done:
|
||||
Pop $6
|
||||
Pop $5
|
||||
Pop $4
|
||||
Pop $3
|
||||
Pop $2
|
||||
Pop $1
|
||||
Pop $0
|
||||
FunctionEnd
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; Uninstall sutff
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
###########################################
|
||||
# Utility Functions #
|
||||
###########################################
|
||||
|
||||
;====================================================
|
||||
; IsNT - Returns 1 if the current system is NT, 0
|
||||
; otherwise.
|
||||
; Output: head of the stack
|
||||
;====================================================
|
||||
; IsNT
|
||||
; no input
|
||||
; output, top of the stack = 1 if NT or 0 if not
|
||||
;
|
||||
; Usage:
|
||||
; Call IsNT
|
||||
; Pop $R0
|
||||
; ($R0 at this point is 1 or 0)
|
||||
|
||||
!macro IsNT un
|
||||
Function ${un}IsNT
|
||||
Push $0
|
||||
ReadRegStr $0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" CurrentVersion
|
||||
StrCmp $0 "" 0 IsNT_yes
|
||||
; we are not NT.
|
||||
Pop $0
|
||||
Push 0
|
||||
Return
|
||||
|
||||
IsNT_yes:
|
||||
; NT!!!
|
||||
Pop $0
|
||||
Push 1
|
||||
FunctionEnd
|
||||
!macroend
|
||||
!insertmacro IsNT ""
|
||||
!insertmacro IsNT "un."
|
||||
|
||||
; StrStr
|
||||
; input, top of stack = string to search for
|
||||
; top of stack-1 = string to search in
|
||||
; output, top of stack (replaces with the portion of the string remaining)
|
||||
; modifies no other variables.
|
||||
;
|
||||
; Usage:
|
||||
; Push "this is a long ass string"
|
||||
; Push "ass"
|
||||
; Call StrStr
|
||||
; Pop $R0
|
||||
; ($R0 at this point is "ass string")
|
||||
|
||||
!macro StrStr un
|
||||
Function ${un}StrStr
|
||||
Exch $R1 ; st=haystack,old$R1, $R1=needle
|
||||
Exch ; st=old$R1,haystack
|
||||
Exch $R2 ; st=old$R1,old$R2, $R2=haystack
|
||||
Push $R3
|
||||
Push $R4
|
||||
Push $R5
|
||||
StrLen $R3 $R1
|
||||
StrCpy $R4 0
|
||||
; $R1=needle
|
||||
; $R2=haystack
|
||||
; $R3=len(needle)
|
||||
; $R4=cnt
|
||||
; $R5=tmp
|
||||
loop:
|
||||
StrCpy $R5 $R2 $R3 $R4
|
||||
StrCmp $R5 $R1 done
|
||||
StrCmp $R5 "" done
|
||||
IntOp $R4 $R4 + 1
|
||||
Goto loop
|
||||
done:
|
||||
StrCpy $R1 $R2 "" $R4
|
||||
Pop $R5
|
||||
Pop $R4
|
||||
Pop $R3
|
||||
Pop $R2
|
||||
Exch $R1
|
||||
FunctionEnd
|
||||
!macroend
|
||||
!insertmacro StrStr ""
|
||||
!insertmacro StrStr "un."
|
||||
|
||||
Function Trim ; Added by Pelaca
|
||||
Exch $R1
|
||||
Push $R2
|
||||
Loop:
|
||||
StrCpy $R2 "$R1" 1 -1
|
||||
StrCmp "$R2" " " RTrim
|
||||
StrCmp "$R2" "$\n" RTrim
|
||||
StrCmp "$R2" "$\r" RTrim
|
||||
StrCmp "$R2" ";" RTrim
|
||||
GoTo Done
|
||||
RTrim:
|
||||
StrCpy $R1 "$R1" -1
|
||||
Goto Loop
|
||||
Done:
|
||||
Pop $R2
|
||||
Exch $R1
|
||||
FunctionEnd
|
||||
|
||||
Function ConditionalAddToRegisty
|
||||
Pop $0
|
||||
Pop $1
|
||||
StrCmp "$0" "" ConditionalAddToRegisty_EmptyString
|
||||
WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@" \
|
||||
"$1" "$0"
|
||||
;MessageBox MB_OK "Set Registry: '$1' to '$0'"
|
||||
DetailPrint "Set install registry entry: '$1' to '$0'"
|
||||
ConditionalAddToRegisty_EmptyString:
|
||||
FunctionEnd
|
||||
|
||||
;--------------------------------
|
||||
|
||||
!ifdef CPACK_USES_DOWNLOAD
|
||||
Function DownloadFile
|
||||
IfFileExists $INSTDIR\* +2
|
||||
CreateDirectory $INSTDIR
|
||||
Pop $0
|
||||
|
||||
; Skip if already downloaded
|
||||
IfFileExists $INSTDIR\$0 0 +2
|
||||
Return
|
||||
|
||||
StrCpy $1 "@CPACK_DOWNLOAD_SITE@"
|
||||
|
||||
try_again:
|
||||
NSISdl::download "$1/$0" "$INSTDIR\$0"
|
||||
|
||||
Pop $1
|
||||
StrCmp $1 "success" success
|
||||
StrCmp $1 "Cancelled" cancel
|
||||
MessageBox MB_OK "Download failed: $1"
|
||||
cancel:
|
||||
Return
|
||||
success:
|
||||
FunctionEnd
|
||||
!endif
|
||||
|
||||
;--------------------------------
|
||||
; Installation types
|
||||
@CPACK_NSIS_INSTALLATION_TYPES@
|
||||
|
||||
;--------------------------------
|
||||
; Component sections
|
||||
@CPACK_NSIS_COMPONENT_SECTIONS@
|
||||
|
||||
;--------------------------------
|
||||
; Define some macro setting for the gui
|
||||
@CPACK_NSIS_INSTALLER_MUI_ICON_CODE@
|
||||
@CPACK_NSIS_INSTALLER_ICON_CODE@
|
||||
@CPACK_NSIS_INSTALLER_MUI_COMPONENTS_DESC@
|
||||
|
||||
;--------------------------------
|
||||
;Pages
|
||||
!insertmacro MUI_PAGE_WELCOME
|
||||
|
||||
!insertmacro MUI_PAGE_LICENSE "@CPACK_RESOURCE_FILE_LICENSE@"
|
||||
Page custom InstallOptionsPage
|
||||
!insertmacro MUI_PAGE_DIRECTORY
|
||||
|
||||
;Start Menu Folder Page Configuration
|
||||
!define MUI_STARTMENUPAGE_REGISTRY_ROOT "SHCTX"
|
||||
!define MUI_STARTMENUPAGE_REGISTRY_KEY "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@"
|
||||
!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "Start Menu Folder"
|
||||
!insertmacro MUI_PAGE_STARTMENU Application $STARTMENU_FOLDER
|
||||
|
||||
!define MUI_FINISHPAGE_SHOWREADME "$INSTDIR\NEWS.txt"
|
||||
|
||||
@CPACK_NSIS_PAGE_COMPONENTS@
|
||||
|
||||
!insertmacro MUI_PAGE_INSTFILES
|
||||
!insertmacro MUI_PAGE_FINISH
|
||||
|
||||
!insertmacro MUI_UNPAGE_CONFIRM
|
||||
!insertmacro MUI_UNPAGE_INSTFILES
|
||||
!insertmacro MUI_UNPAGE_FINISH
|
||||
|
||||
;--------------------------------
|
||||
;Languages
|
||||
|
||||
!insertmacro MUI_LANGUAGE "English" ;first language is the default language
|
||||
!insertmacro MUI_LANGUAGE "Albanian"
|
||||
!insertmacro MUI_LANGUAGE "Arabic"
|
||||
!insertmacro MUI_LANGUAGE "Basque"
|
||||
!insertmacro MUI_LANGUAGE "Belarusian"
|
||||
!insertmacro MUI_LANGUAGE "Bosnian"
|
||||
!insertmacro MUI_LANGUAGE "Breton"
|
||||
!insertmacro MUI_LANGUAGE "Bulgarian"
|
||||
!insertmacro MUI_LANGUAGE "Croatian"
|
||||
!insertmacro MUI_LANGUAGE "Czech"
|
||||
!insertmacro MUI_LANGUAGE "Danish"
|
||||
!insertmacro MUI_LANGUAGE "Dutch"
|
||||
!insertmacro MUI_LANGUAGE "Estonian"
|
||||
!insertmacro MUI_LANGUAGE "Farsi"
|
||||
!insertmacro MUI_LANGUAGE "Finnish"
|
||||
!insertmacro MUI_LANGUAGE "French"
|
||||
!insertmacro MUI_LANGUAGE "German"
|
||||
!insertmacro MUI_LANGUAGE "Greek"
|
||||
!insertmacro MUI_LANGUAGE "Hebrew"
|
||||
!insertmacro MUI_LANGUAGE "Hungarian"
|
||||
!insertmacro MUI_LANGUAGE "Icelandic"
|
||||
!insertmacro MUI_LANGUAGE "Indonesian"
|
||||
!insertmacro MUI_LANGUAGE "Irish"
|
||||
!insertmacro MUI_LANGUAGE "Italian"
|
||||
!insertmacro MUI_LANGUAGE "Japanese"
|
||||
!insertmacro MUI_LANGUAGE "Korean"
|
||||
!insertmacro MUI_LANGUAGE "Kurdish"
|
||||
!insertmacro MUI_LANGUAGE "Latvian"
|
||||
!insertmacro MUI_LANGUAGE "Lithuanian"
|
||||
!insertmacro MUI_LANGUAGE "Luxembourgish"
|
||||
!insertmacro MUI_LANGUAGE "Macedonian"
|
||||
!insertmacro MUI_LANGUAGE "Malay"
|
||||
!insertmacro MUI_LANGUAGE "Mongolian"
|
||||
!insertmacro MUI_LANGUAGE "Norwegian"
|
||||
!insertmacro MUI_LANGUAGE "Polish"
|
||||
!insertmacro MUI_LANGUAGE "Portuguese"
|
||||
!insertmacro MUI_LANGUAGE "PortugueseBR"
|
||||
!insertmacro MUI_LANGUAGE "Romanian"
|
||||
!insertmacro MUI_LANGUAGE "Russian"
|
||||
!insertmacro MUI_LANGUAGE "Serbian"
|
||||
!insertmacro MUI_LANGUAGE "SerbianLatin"
|
||||
!insertmacro MUI_LANGUAGE "SimpChinese"
|
||||
!insertmacro MUI_LANGUAGE "Slovak"
|
||||
!insertmacro MUI_LANGUAGE "Slovenian"
|
||||
!insertmacro MUI_LANGUAGE "Spanish"
|
||||
!insertmacro MUI_LANGUAGE "Swedish"
|
||||
!insertmacro MUI_LANGUAGE "Thai"
|
||||
!insertmacro MUI_LANGUAGE "TradChinese"
|
||||
!insertmacro MUI_LANGUAGE "Turkish"
|
||||
!insertmacro MUI_LANGUAGE "Ukrainian"
|
||||
!insertmacro MUI_LANGUAGE "Welsh"
|
||||
|
||||
|
||||
;--------------------------------
|
||||
;Reserve Files
|
||||
|
||||
;These files should be inserted before other files in the data block
|
||||
;Keep these lines before any File command
|
||||
;Only for solid compression (by default, solid compression is enabled for BZIP2 and LZMA)
|
||||
|
||||
ReserveFile "NSIS.InstallOptions.ini"
|
||||
!insertmacro MUI_RESERVEFILE_INSTALLOPTIONS
|
||||
|
||||
;--------------------------------
|
||||
;Installer Sections
|
||||
|
||||
Section "-Core installation"
|
||||
;Use the entire tree produced by the INSTALL target. Keep the
|
||||
;list of directories here in sync with the RMDir commands below.
|
||||
SetOutPath "$INSTDIR"
|
||||
@CPACK_NSIS_FULL_INSTALL@
|
||||
|
||||
;Store installation folder
|
||||
WriteRegStr SHCTX "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "" $INSTDIR
|
||||
|
||||
;Create uninstaller
|
||||
WriteUninstaller "$INSTDIR\Uninstall.exe"
|
||||
Push "DisplayName"
|
||||
Push "@CPACK_NSIS_DISPLAY_NAME@"
|
||||
Call ConditionalAddToRegisty
|
||||
Push "DisplayVersion"
|
||||
Push "@CPACK_PACKAGE_VERSION@"
|
||||
Call ConditionalAddToRegisty
|
||||
Push "Publisher"
|
||||
Push "@CPACK_PACKAGE_VENDOR@"
|
||||
Call ConditionalAddToRegisty
|
||||
Push "UninstallString"
|
||||
Push "$INSTDIR\Uninstall.exe"
|
||||
Call ConditionalAddToRegisty
|
||||
Push "NoRepair"
|
||||
Push "1"
|
||||
Call ConditionalAddToRegisty
|
||||
|
||||
!ifdef CPACK_NSIS_ADD_REMOVE
|
||||
;Create add/remove functionality
|
||||
Push "ModifyPath"
|
||||
Push "$INSTDIR\AddRemove.exe"
|
||||
Call ConditionalAddToRegisty
|
||||
!else
|
||||
Push "NoModify"
|
||||
Push "1"
|
||||
Call ConditionalAddToRegisty
|
||||
!endif
|
||||
|
||||
; Optional registration
|
||||
Push "DisplayIcon"
|
||||
Push "$INSTDIR\@CPACK_NSIS_INSTALLED_ICON_NAME@"
|
||||
Call ConditionalAddToRegisty
|
||||
Push "HelpLink"
|
||||
Push "@CPACK_NSIS_HELP_LINK@"
|
||||
Call ConditionalAddToRegisty
|
||||
Push "URLInfoAbout"
|
||||
Push "@CPACK_NSIS_URL_INFO_ABOUT@"
|
||||
Call ConditionalAddToRegisty
|
||||
Push "Contact"
|
||||
Push "@CPACK_NSIS_CONTACT@"
|
||||
Call ConditionalAddToRegisty
|
||||
!insertmacro MUI_INSTALLOPTIONS_READ $INSTALL_DESKTOP "NSIS.InstallOptions.ini" "Field 5" "State"
|
||||
!insertmacro MUI_STARTMENU_WRITE_BEGIN Application
|
||||
|
||||
;Create shortcuts
|
||||
CreateDirectory "$SMPROGRAMS\$STARTMENU_FOLDER"
|
||||
@CPACK_NSIS_CREATE_ICONS@
|
||||
@CPACK_NSIS_CREATE_ICONS_EXTRA@
|
||||
CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\Uninstall.lnk" "$INSTDIR\Uninstall.exe"
|
||||
|
||||
;Read a value from an InstallOptions INI file
|
||||
!insertmacro MUI_INSTALLOPTIONS_READ $DO_NOT_ADD_TO_PATH "NSIS.InstallOptions.ini" "Field 2" "State"
|
||||
!insertmacro MUI_INSTALLOPTIONS_READ $ADD_TO_PATH_ALL_USERS "NSIS.InstallOptions.ini" "Field 3" "State"
|
||||
!insertmacro MUI_INSTALLOPTIONS_READ $ADD_TO_PATH_CURRENT_USER "NSIS.InstallOptions.ini" "Field 4" "State"
|
||||
|
||||
; Write special uninstall registry entries
|
||||
Push "StartMenu"
|
||||
Push "$STARTMENU_FOLDER"
|
||||
Call ConditionalAddToRegisty
|
||||
Push "DoNotAddToPath"
|
||||
Push "$DO_NOT_ADD_TO_PATH"
|
||||
Call ConditionalAddToRegisty
|
||||
Push "AddToPathAllUsers"
|
||||
Push "$ADD_TO_PATH_ALL_USERS"
|
||||
Call ConditionalAddToRegisty
|
||||
Push "AddToPathCurrentUser"
|
||||
Push "$ADD_TO_PATH_CURRENT_USER"
|
||||
Call ConditionalAddToRegisty
|
||||
Push "InstallToDesktop"
|
||||
Push "$INSTALL_DESKTOP"
|
||||
Call ConditionalAddToRegisty
|
||||
|
||||
!insertmacro MUI_STARTMENU_WRITE_END
|
||||
|
||||
@CPACK_NSIS_EXTRA_INSTALL_COMMANDS@
|
||||
|
||||
SectionEnd
|
||||
|
||||
Section "-Add to path"
|
||||
Push $INSTDIR\bin
|
||||
StrCmp "@CPACK_NSIS_MODIFY_PATH@" "ON" 0 doNotAddToPath
|
||||
StrCmp $DO_NOT_ADD_TO_PATH "1" doNotAddToPath 0
|
||||
Call AddToPath
|
||||
doNotAddToPath:
|
||||
SectionEnd
|
||||
|
||||
;--------------------------------
|
||||
; Create custom pages
|
||||
Function InstallOptionsPage
|
||||
!insertmacro MUI_HEADER_TEXT "Install Options" "Choose options for installing @CPACK_NSIS_PACKAGE_NAME@"
|
||||
!insertmacro MUI_INSTALLOPTIONS_DISPLAY "NSIS.InstallOptions.ini"
|
||||
|
||||
FunctionEnd
|
||||
|
||||
;--------------------------------
|
||||
; determine admin versus local install
|
||||
Function un.onInit
|
||||
|
||||
ClearErrors
|
||||
UserInfo::GetName
|
||||
IfErrors noLM
|
||||
Pop $0
|
||||
UserInfo::GetAccountType
|
||||
Pop $1
|
||||
StrCmp $1 "Admin" 0 +3
|
||||
SetShellVarContext all
|
||||
;MessageBox MB_OK 'User "$0" is in the Admin group'
|
||||
Goto done
|
||||
StrCmp $1 "Power" 0 +3
|
||||
SetShellVarContext all
|
||||
;MessageBox MB_OK 'User "$0" is in the Power Users group'
|
||||
Goto done
|
||||
|
||||
noLM:
|
||||
;Get installation folder from registry if available
|
||||
|
||||
done:
|
||||
|
||||
FunctionEnd
|
||||
|
||||
;--- Add/Remove callback functions: ---
|
||||
!macro SectionList MacroName
|
||||
;This macro used to perform operation on multiple sections.
|
||||
;List all of your components in following manner here.
|
||||
@CPACK_NSIS_COMPONENT_SECTION_LIST@
|
||||
!macroend
|
||||
|
||||
Section -FinishComponents
|
||||
;Removes unselected components and writes component status to registry
|
||||
!insertmacro SectionList "FinishSection"
|
||||
|
||||
!ifdef CPACK_NSIS_ADD_REMOVE
|
||||
; Get the name of the installer executable
|
||||
System::Call 'kernel32::GetModuleFileNameA(i 0, t .R0, i 1024) i r1'
|
||||
StrCpy $R3 $R0
|
||||
|
||||
; Strip off the last 13 characters, to see if we have AddRemove.exe
|
||||
StrLen $R1 $R0
|
||||
IntOp $R1 $R0 - 13
|
||||
StrCpy $R2 $R0 13 $R1
|
||||
StrCmp $R2 "AddRemove.exe" addremove_installed
|
||||
|
||||
; We're not running AddRemove.exe, so install it
|
||||
CopyFiles $R3 $INSTDIR\AddRemove.exe
|
||||
|
||||
addremove_installed:
|
||||
!endif
|
||||
SectionEnd
|
||||
;--- End of Add/Remove callback functions ---
|
||||
|
||||
;--------------------------------
|
||||
; Component dependencies
|
||||
Function .onSelChange
|
||||
!insertmacro SectionList MaybeSelectionChanged
|
||||
FunctionEnd
|
||||
|
||||
;--------------------------------
|
||||
;Uninstaller Section
|
||||
|
||||
Section "Uninstall"
|
||||
ReadRegStr $START_MENU SHCTX \
|
||||
"Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@" "StartMenu"
|
||||
;MessageBox MB_OK "Start menu is in: $START_MENU"
|
||||
ReadRegStr $DO_NOT_ADD_TO_PATH SHCTX \
|
||||
"Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@" "DoNotAddToPath"
|
||||
ReadRegStr $ADD_TO_PATH_ALL_USERS SHCTX \
|
||||
"Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@" "AddToPathAllUsers"
|
||||
ReadRegStr $ADD_TO_PATH_CURRENT_USER SHCTX \
|
||||
"Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@" "AddToPathCurrentUser"
|
||||
;MessageBox MB_OK "Add to path: $DO_NOT_ADD_TO_PATH all users: $ADD_TO_PATH_ALL_USERS"
|
||||
ReadRegStr $INSTALL_DESKTOP SHCTX \
|
||||
"Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@" "InstallToDesktop"
|
||||
;MessageBox MB_OK "Install to desktop: $INSTALL_DESKTOP "
|
||||
|
||||
@CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS@
|
||||
|
||||
;Remove files we installed.
|
||||
;Keep the list of directories here in sync with the File commands above.
|
||||
@CPACK_NSIS_DELETE_FILES@
|
||||
@CPACK_NSIS_DELETE_DIRECTORIES@
|
||||
|
||||
!ifdef CPACK_NSIS_ADD_REMOVE
|
||||
;Remove the add/remove program
|
||||
Delete "$INSTDIR\AddRemove.exe"
|
||||
!endif
|
||||
|
||||
;Remove the uninstaller itself.
|
||||
Delete "$INSTDIR\Uninstall.exe"
|
||||
DeleteRegKey SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@"
|
||||
|
||||
;Remove the installation directory if it is empty.
|
||||
RMDir "$INSTDIR"
|
||||
|
||||
; Remove the registry entries.
|
||||
DeleteRegKey SHCTX "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@"
|
||||
|
||||
; Removes all optional components
|
||||
!insertmacro SectionList "RemoveSection"
|
||||
|
||||
!insertmacro MUI_STARTMENU_GETFOLDER Application $MUI_TEMP
|
||||
|
||||
Delete "$SMPROGRAMS\$MUI_TEMP\Uninstall.lnk"
|
||||
@CPACK_NSIS_DELETE_ICONS@
|
||||
@CPACK_NSIS_DELETE_ICONS_EXTRA@
|
||||
|
||||
;Delete empty start menu parent diretories
|
||||
StrCpy $MUI_TEMP "$SMPROGRAMS\$MUI_TEMP"
|
||||
|
||||
startMenuDeleteLoop:
|
||||
ClearErrors
|
||||
RMDir $MUI_TEMP
|
||||
GetFullPathName $MUI_TEMP "$MUI_TEMP\.."
|
||||
|
||||
IfErrors startMenuDeleteLoopDone
|
||||
|
||||
StrCmp "$MUI_TEMP" "$SMPROGRAMS" startMenuDeleteLoopDone startMenuDeleteLoop
|
||||
startMenuDeleteLoopDone:
|
||||
|
||||
; If the user changed the shortcut, then untinstall may not work. This should
|
||||
; try to fix it.
|
||||
StrCpy $MUI_TEMP "$START_MENU"
|
||||
Delete "$SMPROGRAMS\$MUI_TEMP\Uninstall.lnk"
|
||||
@CPACK_NSIS_DELETE_ICONS_EXTRA@
|
||||
|
||||
;Delete empty start menu parent diretories
|
||||
StrCpy $MUI_TEMP "$SMPROGRAMS\$MUI_TEMP"
|
||||
|
||||
secondStartMenuDeleteLoop:
|
||||
ClearErrors
|
||||
RMDir $MUI_TEMP
|
||||
GetFullPathName $MUI_TEMP "$MUI_TEMP\.."
|
||||
|
||||
IfErrors secondStartMenuDeleteLoopDone
|
||||
|
||||
StrCmp "$MUI_TEMP" "$SMPROGRAMS" secondStartMenuDeleteLoopDone secondStartMenuDeleteLoop
|
||||
secondStartMenuDeleteLoopDone:
|
||||
|
||||
DeleteRegKey /ifempty SHCTX "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@"
|
||||
|
||||
Push $INSTDIR\bin
|
||||
StrCmp $DO_NOT_ADD_TO_PATH_ "1" doNotRemoveFromPath 0
|
||||
Call un.RemoveFromPath
|
||||
doNotRemoveFromPath:
|
||||
SectionEnd
|
||||
|
||||
;--------------------------------
|
||||
; determine admin versus local install
|
||||
; Is install for "AllUsers" or "JustMe"?
|
||||
; Default to "JustMe" - set to "AllUsers" if admin or on Win9x
|
||||
; This function is used for the very first "custom page" of the installer.
|
||||
; This custom page does not show up visibly, but it executes prior to the
|
||||
; first visible page and sets up $INSTDIR properly...
|
||||
; Choose different default installation folder based on SV_ALLUSERS...
|
||||
; "Program Files" for AllUsers, "My Documents" for JustMe...
|
||||
|
||||
Function .onInit
|
||||
; Reads components status for registry
|
||||
!insertmacro SectionList "InitSection"
|
||||
|
||||
; check to see if /D has been used to change
|
||||
; the install directory by comparing it to the
|
||||
; install directory that is expected to be the
|
||||
; default
|
||||
StrCpy $IS_DEFAULT_INSTALLDIR 0
|
||||
StrCmp "$INSTDIR" "$PROGRAMFILES\@CPACK_PACKAGE_INSTALL_DIRECTORY@" 0 +2
|
||||
StrCpy $IS_DEFAULT_INSTALLDIR 1
|
||||
|
||||
StrCpy $SV_ALLUSERS "JustMe"
|
||||
; if default install dir then change the default
|
||||
; if it is installed for JustMe
|
||||
StrCmp "$IS_DEFAULT_INSTALLDIR" "1" 0 +2
|
||||
StrCpy $INSTDIR "$DOCUMENTS\@CPACK_PACKAGE_INSTALL_DIRECTORY@"
|
||||
|
||||
ClearErrors
|
||||
UserInfo::GetName
|
||||
IfErrors noLM
|
||||
Pop $0
|
||||
UserInfo::GetAccountType
|
||||
Pop $1
|
||||
StrCmp $1 "Admin" 0 +3
|
||||
SetShellVarContext all
|
||||
;MessageBox MB_OK 'User "$0" is in the Admin group'
|
||||
StrCpy $SV_ALLUSERS "AllUsers"
|
||||
Goto done
|
||||
StrCmp $1 "Power" 0 +3
|
||||
SetShellVarContext all
|
||||
;MessageBox MB_OK 'User "$0" is in the Power Users group'
|
||||
StrCpy $SV_ALLUSERS "AllUsers"
|
||||
Goto done
|
||||
|
||||
noLM:
|
||||
StrCpy $SV_ALLUSERS "AllUsers"
|
||||
;Get installation folder from registry if available
|
||||
|
||||
done:
|
||||
StrCmp $SV_ALLUSERS "AllUsers" 0 +3
|
||||
StrCmp "$IS_DEFAULT_INSTALLDIR" "1" 0 +2
|
||||
StrCpy $INSTDIR "$PROGRAMFILES\@CPACK_PACKAGE_INSTALL_DIRECTORY@"
|
||||
|
||||
StrCmp "@CPACK_NSIS_MODIFY_PATH@" "ON" 0 noOptionsPage
|
||||
!insertmacro MUI_INSTALLOPTIONS_EXTRACT "NSIS.InstallOptions.ini"
|
||||
|
||||
noOptionsPage:
|
||||
FunctionEnd
|
||||
960
3rd/libzmq/builds/cmake/NSIS.template64.in
Normal file
960
3rd/libzmq/builds/cmake/NSIS.template64.in
Normal file
@@ -0,0 +1,960 @@
|
||||
; CPack install script designed for a nmake build
|
||||
|
||||
;--------------------------------
|
||||
; You must define these values
|
||||
|
||||
!define VERSION "@CPACK_PACKAGE_VERSION@"
|
||||
!define PATCH "@CPACK_PACKAGE_VERSION_PATCH@"
|
||||
!define INST_DIR "@CPACK_TEMPORARY_DIRECTORY@"
|
||||
|
||||
;--------------------------------
|
||||
;Variables
|
||||
|
||||
Var MUI_TEMP
|
||||
Var STARTMENU_FOLDER
|
||||
Var SV_ALLUSERS
|
||||
Var START_MENU
|
||||
Var DO_NOT_ADD_TO_PATH
|
||||
Var ADD_TO_PATH_ALL_USERS
|
||||
Var ADD_TO_PATH_CURRENT_USER
|
||||
Var INSTALL_DESKTOP
|
||||
Var IS_DEFAULT_INSTALLDIR
|
||||
;--------------------------------
|
||||
;Include Modern UI
|
||||
|
||||
!include "MUI.nsh"
|
||||
|
||||
;Default installation folder
|
||||
;InstallDir "$PROGRAMFILES\@CPACK_PACKAGE_INSTALL_DIRECTORY@"
|
||||
InstallDir "$PROGRAMFILES64\@CPACK_PACKAGE_INSTALL_DIRECTORY@"
|
||||
|
||||
;--------------------------------
|
||||
;General
|
||||
|
||||
;Name and file
|
||||
Name "@CPACK_NSIS_PACKAGE_NAME@"
|
||||
OutFile "@CPACK_TOPLEVEL_DIRECTORY@/@CPACK_OUTPUT_FILE_NAME@"
|
||||
|
||||
;Set compression
|
||||
SetCompressor @CPACK_NSIS_COMPRESSOR@
|
||||
|
||||
@CPACK_NSIS_DEFINES@
|
||||
|
||||
!include Sections.nsh
|
||||
|
||||
;--- Component support macros: ---
|
||||
; The code for the add/remove functionality is from:
|
||||
; http://nsis.sourceforge.net/Add/Remove_Functionality
|
||||
; It has been modified slightly and extended to provide
|
||||
; inter-component dependencies.
|
||||
Var AR_SecFlags
|
||||
Var AR_RegFlags
|
||||
@CPACK_NSIS_SECTION_SELECTED_VARS@
|
||||
|
||||
; Loads the "selected" flag for the section named SecName into the
|
||||
; variable VarName.
|
||||
!macro LoadSectionSelectedIntoVar SecName VarName
|
||||
SectionGetFlags ${${SecName}} $${VarName}
|
||||
IntOp $${VarName} $${VarName} & ${SF_SELECTED} ;Turn off all other bits
|
||||
!macroend
|
||||
|
||||
; Loads the value of a variable... can we get around this?
|
||||
!macro LoadVar VarName
|
||||
IntOp $R0 0 + $${VarName}
|
||||
!macroend
|
||||
|
||||
; Sets the value of a variable
|
||||
!macro StoreVar VarName IntValue
|
||||
IntOp $${VarName} 0 + ${IntValue}
|
||||
!macroend
|
||||
|
||||
!macro InitSection SecName
|
||||
; This macro reads component installed flag from the registry and
|
||||
;changes checked state of the section on the components page.
|
||||
;Input: section index constant name specified in Section command.
|
||||
|
||||
ClearErrors
|
||||
;Reading component status from registry
|
||||
ReadRegDWORD $AR_RegFlags HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@ (x64)\Components\${SecName}" "Installed"
|
||||
IfErrors "default_${SecName}"
|
||||
;Status will stay default if registry value not found
|
||||
;(component was never installed)
|
||||
IntOp $AR_RegFlags $AR_RegFlags & ${SF_SELECTED} ;Turn off all other bits
|
||||
SectionGetFlags ${${SecName}} $AR_SecFlags ;Reading default section flags
|
||||
IntOp $AR_SecFlags $AR_SecFlags & 0xFFFE ;Turn lowest (enabled) bit off
|
||||
IntOp $AR_SecFlags $AR_RegFlags | $AR_SecFlags ;Change lowest bit
|
||||
|
||||
; Note whether this component was installed before
|
||||
!insertmacro StoreVar ${SecName}_was_installed $AR_RegFlags
|
||||
IntOp $R0 $AR_RegFlags & $AR_RegFlags
|
||||
|
||||
;Writing modified flags
|
||||
SectionSetFlags ${${SecName}} $AR_SecFlags
|
||||
|
||||
"default_${SecName}:"
|
||||
!insertmacro LoadSectionSelectedIntoVar ${SecName} ${SecName}_selected
|
||||
!macroend
|
||||
|
||||
!macro FinishSection SecName
|
||||
; This macro reads section flag set by user and removes the section
|
||||
;if it is not selected.
|
||||
;Then it writes component installed flag to registry
|
||||
;Input: section index constant name specified in Section command.
|
||||
|
||||
SectionGetFlags ${${SecName}} $AR_SecFlags ;Reading section flags
|
||||
;Checking lowest bit:
|
||||
IntOp $AR_SecFlags $AR_SecFlags & ${SF_SELECTED}
|
||||
IntCmp $AR_SecFlags 1 "leave_${SecName}"
|
||||
;Section is not selected:
|
||||
;Calling Section uninstall macro and writing zero installed flag
|
||||
!insertmacro "Remove_${${SecName}}"
|
||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@ (x64)\Components\${SecName}" \
|
||||
"Installed" 0
|
||||
Goto "exit_${SecName}"
|
||||
|
||||
"leave_${SecName}:"
|
||||
;Section is selected:
|
||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@ (x64)\Components\${SecName}" \
|
||||
"Installed" 1
|
||||
|
||||
"exit_${SecName}:"
|
||||
!macroend
|
||||
|
||||
!macro RemoveSection SecName
|
||||
; This macro is used to call section's Remove_... macro
|
||||
;from the uninstaller.
|
||||
;Input: section index constant name specified in Section command.
|
||||
|
||||
!insertmacro "Remove_${${SecName}}"
|
||||
!macroend
|
||||
|
||||
; Determine whether the selection of SecName changed
|
||||
!macro MaybeSelectionChanged SecName
|
||||
!insertmacro LoadVar ${SecName}_selected
|
||||
SectionGetFlags ${${SecName}} $R1
|
||||
IntOp $R1 $R1 & ${SF_SELECTED} ;Turn off all other bits
|
||||
|
||||
; See if the status has changed:
|
||||
IntCmp $R0 $R1 "${SecName}_unchanged"
|
||||
!insertmacro LoadSectionSelectedIntoVar ${SecName} ${SecName}_selected
|
||||
|
||||
IntCmp $R1 ${SF_SELECTED} "${SecName}_was_selected"
|
||||
!insertmacro "Deselect_required_by_${SecName}"
|
||||
goto "${SecName}_unchanged"
|
||||
|
||||
"${SecName}_was_selected:"
|
||||
!insertmacro "Select_${SecName}_depends"
|
||||
|
||||
"${SecName}_unchanged:"
|
||||
!macroend
|
||||
;--- End of Add/Remove macros ---
|
||||
|
||||
;--------------------------------
|
||||
;Interface Settings
|
||||
|
||||
!define MUI_HEADERIMAGE
|
||||
!define MUI_ABORTWARNING
|
||||
|
||||
;--------------------------------
|
||||
; path functions
|
||||
|
||||
!verbose 3
|
||||
!include "WinMessages.NSH"
|
||||
!verbose 4
|
||||
|
||||
;----------------------------------------
|
||||
; based upon a script of "Written by KiCHiK 2003-01-18 05:57:02"
|
||||
;----------------------------------------
|
||||
!verbose 3
|
||||
!include "WinMessages.NSH"
|
||||
!verbose 4
|
||||
;====================================================
|
||||
; get_NT_environment
|
||||
; Returns: the selected environment
|
||||
; Output : head of the stack
|
||||
;====================================================
|
||||
!macro select_NT_profile UN
|
||||
Function ${UN}select_NT_profile
|
||||
StrCmp $ADD_TO_PATH_ALL_USERS "1" 0 environment_single
|
||||
DetailPrint "Selected environment for all users"
|
||||
Push "all"
|
||||
Return
|
||||
environment_single:
|
||||
DetailPrint "Selected environment for current user only."
|
||||
Push "current"
|
||||
Return
|
||||
FunctionEnd
|
||||
!macroend
|
||||
!insertmacro select_NT_profile ""
|
||||
!insertmacro select_NT_profile "un."
|
||||
;----------------------------------------------------
|
||||
!define NT_current_env 'HKCU "Environment"'
|
||||
!define NT_all_env 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"'
|
||||
|
||||
!ifndef WriteEnvStr_RegKey
|
||||
!ifdef ALL_USERS
|
||||
!define WriteEnvStr_RegKey \
|
||||
'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"'
|
||||
!else
|
||||
!define WriteEnvStr_RegKey 'HKCU "Environment"'
|
||||
!endif
|
||||
!endif
|
||||
|
||||
; AddToPath - Adds the given dir to the search path.
|
||||
; Input - head of the stack
|
||||
; Note - Win9x systems requires reboot
|
||||
|
||||
Function AddToPath
|
||||
Exch $0
|
||||
Push $1
|
||||
Push $2
|
||||
Push $3
|
||||
|
||||
# don't add if the path doesn't exist
|
||||
IfFileExists "$0\*.*" "" AddToPath_done
|
||||
|
||||
ReadEnvStr $1 PATH
|
||||
; if the path is too long for a NSIS variable NSIS will return a 0
|
||||
; length string. If we find that, then warn and skip any path
|
||||
; modification as it will trash the existing path.
|
||||
StrLen $2 $1
|
||||
IntCmp $2 0 CheckPathLength_ShowPathWarning CheckPathLength_Done CheckPathLength_Done
|
||||
CheckPathLength_ShowPathWarning:
|
||||
Messagebox MB_OK|MB_ICONEXCLAMATION "Warning! PATH too long installer unable to modify PATH!"
|
||||
Goto AddToPath_done
|
||||
CheckPathLength_Done:
|
||||
Push "$1;"
|
||||
Push "$0;"
|
||||
Call StrStr
|
||||
Pop $2
|
||||
StrCmp $2 "" "" AddToPath_done
|
||||
Push "$1;"
|
||||
Push "$0\;"
|
||||
Call StrStr
|
||||
Pop $2
|
||||
StrCmp $2 "" "" AddToPath_done
|
||||
GetFullPathName /SHORT $3 $0
|
||||
Push "$1;"
|
||||
Push "$3;"
|
||||
Call StrStr
|
||||
Pop $2
|
||||
StrCmp $2 "" "" AddToPath_done
|
||||
Push "$1;"
|
||||
Push "$3\;"
|
||||
Call StrStr
|
||||
Pop $2
|
||||
StrCmp $2 "" "" AddToPath_done
|
||||
|
||||
Call IsNT
|
||||
Pop $1
|
||||
StrCmp $1 1 AddToPath_NT
|
||||
; Not on NT
|
||||
StrCpy $1 $WINDIR 2
|
||||
FileOpen $1 "$1\autoexec.bat" a
|
||||
FileSeek $1 -1 END
|
||||
FileReadByte $1 $2
|
||||
IntCmp $2 26 0 +2 +2 # DOS EOF
|
||||
FileSeek $1 -1 END # write over EOF
|
||||
FileWrite $1 "$\r$\nSET PATH=%PATH%;$3$\r$\n"
|
||||
FileClose $1
|
||||
SetRebootFlag true
|
||||
Goto AddToPath_done
|
||||
|
||||
AddToPath_NT:
|
||||
StrCmp $ADD_TO_PATH_ALL_USERS "1" ReadAllKey
|
||||
ReadRegStr $1 ${NT_current_env} "PATH"
|
||||
Goto DoTrim
|
||||
ReadAllKey:
|
||||
ReadRegStr $1 ${NT_all_env} "PATH"
|
||||
DoTrim:
|
||||
StrCmp $1 "" AddToPath_NTdoIt
|
||||
Push $1
|
||||
Call Trim
|
||||
Pop $1
|
||||
StrCpy $0 "$1;$0"
|
||||
AddToPath_NTdoIt:
|
||||
StrCmp $ADD_TO_PATH_ALL_USERS "1" WriteAllKey
|
||||
WriteRegExpandStr ${NT_current_env} "PATH" $0
|
||||
Goto DoSend
|
||||
WriteAllKey:
|
||||
WriteRegExpandStr ${NT_all_env} "PATH" $0
|
||||
DoSend:
|
||||
SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
|
||||
|
||||
AddToPath_done:
|
||||
Pop $3
|
||||
Pop $2
|
||||
Pop $1
|
||||
Pop $0
|
||||
FunctionEnd
|
||||
|
||||
|
||||
; RemoveFromPath - Remove a given dir from the path
|
||||
; Input: head of the stack
|
||||
|
||||
Function un.RemoveFromPath
|
||||
Exch $0
|
||||
Push $1
|
||||
Push $2
|
||||
Push $3
|
||||
Push $4
|
||||
Push $5
|
||||
Push $6
|
||||
|
||||
IntFmt $6 "%c" 26 # DOS EOF
|
||||
|
||||
Call un.IsNT
|
||||
Pop $1
|
||||
StrCmp $1 1 unRemoveFromPath_NT
|
||||
; Not on NT
|
||||
StrCpy $1 $WINDIR 2
|
||||
FileOpen $1 "$1\autoexec.bat" r
|
||||
GetTempFileName $4
|
||||
FileOpen $2 $4 w
|
||||
GetFullPathName /SHORT $0 $0
|
||||
StrCpy $0 "SET PATH=%PATH%;$0"
|
||||
Goto unRemoveFromPath_dosLoop
|
||||
|
||||
unRemoveFromPath_dosLoop:
|
||||
FileRead $1 $3
|
||||
StrCpy $5 $3 1 -1 # read last char
|
||||
StrCmp $5 $6 0 +2 # if DOS EOF
|
||||
StrCpy $3 $3 -1 # remove DOS EOF so we can compare
|
||||
StrCmp $3 "$0$\r$\n" unRemoveFromPath_dosLoopRemoveLine
|
||||
StrCmp $3 "$0$\n" unRemoveFromPath_dosLoopRemoveLine
|
||||
StrCmp $3 "$0" unRemoveFromPath_dosLoopRemoveLine
|
||||
StrCmp $3 "" unRemoveFromPath_dosLoopEnd
|
||||
FileWrite $2 $3
|
||||
Goto unRemoveFromPath_dosLoop
|
||||
unRemoveFromPath_dosLoopRemoveLine:
|
||||
SetRebootFlag true
|
||||
Goto unRemoveFromPath_dosLoop
|
||||
|
||||
unRemoveFromPath_dosLoopEnd:
|
||||
FileClose $2
|
||||
FileClose $1
|
||||
StrCpy $1 $WINDIR 2
|
||||
Delete "$1\autoexec.bat"
|
||||
CopyFiles /SILENT $4 "$1\autoexec.bat"
|
||||
Delete $4
|
||||
Goto unRemoveFromPath_done
|
||||
|
||||
unRemoveFromPath_NT:
|
||||
StrCmp $ADD_TO_PATH_ALL_USERS "1" unReadAllKey
|
||||
ReadRegStr $1 ${NT_current_env} "PATH"
|
||||
Goto unDoTrim
|
||||
unReadAllKey:
|
||||
ReadRegStr $1 ${NT_all_env} "PATH"
|
||||
unDoTrim:
|
||||
StrCpy $5 $1 1 -1 # copy last char
|
||||
StrCmp $5 ";" +2 # if last char != ;
|
||||
StrCpy $1 "$1;" # append ;
|
||||
Push $1
|
||||
Push "$0;"
|
||||
Call un.StrStr ; Find `$0;` in $1
|
||||
Pop $2 ; pos of our dir
|
||||
StrCmp $2 "" unRemoveFromPath_done
|
||||
; else, it is in path
|
||||
# $0 - path to add
|
||||
# $1 - path var
|
||||
StrLen $3 "$0;"
|
||||
StrLen $4 $2
|
||||
StrCpy $5 $1 -$4 # $5 is now the part before the path to remove
|
||||
StrCpy $6 $2 "" $3 # $6 is now the part after the path to remove
|
||||
StrCpy $3 $5$6
|
||||
|
||||
StrCpy $5 $3 1 -1 # copy last char
|
||||
StrCmp $5 ";" 0 +2 # if last char == ;
|
||||
StrCpy $3 $3 -1 # remove last char
|
||||
|
||||
StrCmp $ADD_TO_PATH_ALL_USERS "1" unWriteAllKey
|
||||
WriteRegExpandStr ${NT_current_env} "PATH" $3
|
||||
Goto unDoSend
|
||||
unWriteAllKey:
|
||||
WriteRegExpandStr ${NT_all_env} "PATH" $3
|
||||
unDoSend:
|
||||
SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
|
||||
|
||||
unRemoveFromPath_done:
|
||||
Pop $6
|
||||
Pop $5
|
||||
Pop $4
|
||||
Pop $3
|
||||
Pop $2
|
||||
Pop $1
|
||||
Pop $0
|
||||
FunctionEnd
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; Uninstall sutff
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
###########################################
|
||||
# Utility Functions #
|
||||
###########################################
|
||||
|
||||
;====================================================
|
||||
; IsNT - Returns 1 if the current system is NT, 0
|
||||
; otherwise.
|
||||
; Output: head of the stack
|
||||
;====================================================
|
||||
; IsNT
|
||||
; no input
|
||||
; output, top of the stack = 1 if NT or 0 if not
|
||||
;
|
||||
; Usage:
|
||||
; Call IsNT
|
||||
; Pop $R0
|
||||
; ($R0 at this point is 1 or 0)
|
||||
|
||||
!macro IsNT un
|
||||
Function ${un}IsNT
|
||||
Push $0
|
||||
ReadRegStr $0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" CurrentVersion
|
||||
StrCmp $0 "" 0 IsNT_yes
|
||||
; we are not NT.
|
||||
Pop $0
|
||||
Push 0
|
||||
Return
|
||||
|
||||
IsNT_yes:
|
||||
; NT!!!
|
||||
Pop $0
|
||||
Push 1
|
||||
FunctionEnd
|
||||
!macroend
|
||||
!insertmacro IsNT ""
|
||||
!insertmacro IsNT "un."
|
||||
|
||||
; StrStr
|
||||
; input, top of stack = string to search for
|
||||
; top of stack-1 = string to search in
|
||||
; output, top of stack (replaces with the portion of the string remaining)
|
||||
; modifies no other variables.
|
||||
;
|
||||
; Usage:
|
||||
; Push "this is a long ass string"
|
||||
; Push "ass"
|
||||
; Call StrStr
|
||||
; Pop $R0
|
||||
; ($R0 at this point is "ass string")
|
||||
|
||||
!macro StrStr un
|
||||
Function ${un}StrStr
|
||||
Exch $R1 ; st=haystack,old$R1, $R1=needle
|
||||
Exch ; st=old$R1,haystack
|
||||
Exch $R2 ; st=old$R1,old$R2, $R2=haystack
|
||||
Push $R3
|
||||
Push $R4
|
||||
Push $R5
|
||||
StrLen $R3 $R1
|
||||
StrCpy $R4 0
|
||||
; $R1=needle
|
||||
; $R2=haystack
|
||||
; $R3=len(needle)
|
||||
; $R4=cnt
|
||||
; $R5=tmp
|
||||
loop:
|
||||
StrCpy $R5 $R2 $R3 $R4
|
||||
StrCmp $R5 $R1 done
|
||||
StrCmp $R5 "" done
|
||||
IntOp $R4 $R4 + 1
|
||||
Goto loop
|
||||
done:
|
||||
StrCpy $R1 $R2 "" $R4
|
||||
Pop $R5
|
||||
Pop $R4
|
||||
Pop $R3
|
||||
Pop $R2
|
||||
Exch $R1
|
||||
FunctionEnd
|
||||
!macroend
|
||||
!insertmacro StrStr ""
|
||||
!insertmacro StrStr "un."
|
||||
|
||||
Function Trim ; Added by Pelaca
|
||||
Exch $R1
|
||||
Push $R2
|
||||
Loop:
|
||||
StrCpy $R2 "$R1" 1 -1
|
||||
StrCmp "$R2" " " RTrim
|
||||
StrCmp "$R2" "$\n" RTrim
|
||||
StrCmp "$R2" "$\r" RTrim
|
||||
StrCmp "$R2" ";" RTrim
|
||||
GoTo Done
|
||||
RTrim:
|
||||
StrCpy $R1 "$R1" -1
|
||||
Goto Loop
|
||||
Done:
|
||||
Pop $R2
|
||||
Exch $R1
|
||||
FunctionEnd
|
||||
|
||||
Function ConditionalAddToRegisty
|
||||
Pop $0
|
||||
Pop $1
|
||||
StrCmp "$0" "" ConditionalAddToRegisty_EmptyString
|
||||
WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@ (x64)" \
|
||||
"$1" "$0"
|
||||
;MessageBox MB_OK "Set Registry: '$1' to '$0'"
|
||||
DetailPrint "Set install registry entry: '$1' to '$0'"
|
||||
ConditionalAddToRegisty_EmptyString:
|
||||
FunctionEnd
|
||||
|
||||
;--------------------------------
|
||||
|
||||
!ifdef CPACK_USES_DOWNLOAD
|
||||
Function DownloadFile
|
||||
IfFileExists $INSTDIR\* +2
|
||||
CreateDirectory $INSTDIR
|
||||
Pop $0
|
||||
|
||||
; Skip if already downloaded
|
||||
IfFileExists $INSTDIR\$0 0 +2
|
||||
Return
|
||||
|
||||
StrCpy $1 "@CPACK_DOWNLOAD_SITE@"
|
||||
|
||||
try_again:
|
||||
NSISdl::download "$1/$0" "$INSTDIR\$0"
|
||||
|
||||
Pop $1
|
||||
StrCmp $1 "success" success
|
||||
StrCmp $1 "Cancelled" cancel
|
||||
MessageBox MB_OK "Download failed: $1"
|
||||
cancel:
|
||||
Return
|
||||
success:
|
||||
FunctionEnd
|
||||
!endif
|
||||
|
||||
;--------------------------------
|
||||
; Installation types
|
||||
@CPACK_NSIS_INSTALLATION_TYPES@
|
||||
|
||||
;--------------------------------
|
||||
; Component sections
|
||||
@CPACK_NSIS_COMPONENT_SECTIONS@
|
||||
|
||||
;--------------------------------
|
||||
; Define some macro setting for the gui
|
||||
@CPACK_NSIS_INSTALLER_MUI_ICON_CODE@
|
||||
@CPACK_NSIS_INSTALLER_ICON_CODE@
|
||||
@CPACK_NSIS_INSTALLER_MUI_COMPONENTS_DESC@
|
||||
|
||||
;--------------------------------
|
||||
;Pages
|
||||
!insertmacro MUI_PAGE_WELCOME
|
||||
|
||||
!insertmacro MUI_PAGE_LICENSE "@CPACK_RESOURCE_FILE_LICENSE@"
|
||||
Page custom InstallOptionsPage
|
||||
!insertmacro MUI_PAGE_DIRECTORY
|
||||
|
||||
;Start Menu Folder Page Configuration
|
||||
!define MUI_STARTMENUPAGE_REGISTRY_ROOT "SHCTX"
|
||||
!define MUI_STARTMENUPAGE_REGISTRY_KEY "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@"
|
||||
!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "Start Menu Folder"
|
||||
!insertmacro MUI_PAGE_STARTMENU Application $STARTMENU_FOLDER
|
||||
|
||||
!define MUI_FINISHPAGE_SHOWREADME "$INSTDIR\NEWS.txt"
|
||||
|
||||
@CPACK_NSIS_PAGE_COMPONENTS@
|
||||
|
||||
!insertmacro MUI_PAGE_INSTFILES
|
||||
!insertmacro MUI_PAGE_FINISH
|
||||
|
||||
!insertmacro MUI_UNPAGE_CONFIRM
|
||||
!insertmacro MUI_UNPAGE_INSTFILES
|
||||
!insertmacro MUI_UNPAGE_FINISH
|
||||
|
||||
;--------------------------------
|
||||
;Languages
|
||||
|
||||
!insertmacro MUI_LANGUAGE "English" ;first language is the default language
|
||||
!insertmacro MUI_LANGUAGE "Albanian"
|
||||
!insertmacro MUI_LANGUAGE "Arabic"
|
||||
!insertmacro MUI_LANGUAGE "Basque"
|
||||
!insertmacro MUI_LANGUAGE "Belarusian"
|
||||
!insertmacro MUI_LANGUAGE "Bosnian"
|
||||
!insertmacro MUI_LANGUAGE "Breton"
|
||||
!insertmacro MUI_LANGUAGE "Bulgarian"
|
||||
!insertmacro MUI_LANGUAGE "Croatian"
|
||||
!insertmacro MUI_LANGUAGE "Czech"
|
||||
!insertmacro MUI_LANGUAGE "Danish"
|
||||
!insertmacro MUI_LANGUAGE "Dutch"
|
||||
!insertmacro MUI_LANGUAGE "Estonian"
|
||||
!insertmacro MUI_LANGUAGE "Farsi"
|
||||
!insertmacro MUI_LANGUAGE "Finnish"
|
||||
!insertmacro MUI_LANGUAGE "French"
|
||||
!insertmacro MUI_LANGUAGE "German"
|
||||
!insertmacro MUI_LANGUAGE "Greek"
|
||||
!insertmacro MUI_LANGUAGE "Hebrew"
|
||||
!insertmacro MUI_LANGUAGE "Hungarian"
|
||||
!insertmacro MUI_LANGUAGE "Icelandic"
|
||||
!insertmacro MUI_LANGUAGE "Indonesian"
|
||||
!insertmacro MUI_LANGUAGE "Irish"
|
||||
!insertmacro MUI_LANGUAGE "Italian"
|
||||
!insertmacro MUI_LANGUAGE "Japanese"
|
||||
!insertmacro MUI_LANGUAGE "Korean"
|
||||
!insertmacro MUI_LANGUAGE "Kurdish"
|
||||
!insertmacro MUI_LANGUAGE "Latvian"
|
||||
!insertmacro MUI_LANGUAGE "Lithuanian"
|
||||
!insertmacro MUI_LANGUAGE "Luxembourgish"
|
||||
!insertmacro MUI_LANGUAGE "Macedonian"
|
||||
!insertmacro MUI_LANGUAGE "Malay"
|
||||
!insertmacro MUI_LANGUAGE "Mongolian"
|
||||
!insertmacro MUI_LANGUAGE "Norwegian"
|
||||
!insertmacro MUI_LANGUAGE "Polish"
|
||||
!insertmacro MUI_LANGUAGE "Portuguese"
|
||||
!insertmacro MUI_LANGUAGE "PortugueseBR"
|
||||
!insertmacro MUI_LANGUAGE "Romanian"
|
||||
!insertmacro MUI_LANGUAGE "Russian"
|
||||
!insertmacro MUI_LANGUAGE "Serbian"
|
||||
!insertmacro MUI_LANGUAGE "SerbianLatin"
|
||||
!insertmacro MUI_LANGUAGE "SimpChinese"
|
||||
!insertmacro MUI_LANGUAGE "Slovak"
|
||||
!insertmacro MUI_LANGUAGE "Slovenian"
|
||||
!insertmacro MUI_LANGUAGE "Spanish"
|
||||
!insertmacro MUI_LANGUAGE "Swedish"
|
||||
!insertmacro MUI_LANGUAGE "Thai"
|
||||
!insertmacro MUI_LANGUAGE "TradChinese"
|
||||
!insertmacro MUI_LANGUAGE "Turkish"
|
||||
!insertmacro MUI_LANGUAGE "Ukrainian"
|
||||
!insertmacro MUI_LANGUAGE "Welsh"
|
||||
|
||||
|
||||
;--------------------------------
|
||||
;Reserve Files
|
||||
|
||||
;These files should be inserted before other files in the data block
|
||||
;Keep these lines before any File command
|
||||
;Only for solid compression (by default, solid compression is enabled for BZIP2 and LZMA)
|
||||
|
||||
ReserveFile "NSIS.InstallOptions.ini"
|
||||
!insertmacro MUI_RESERVEFILE_INSTALLOPTIONS
|
||||
|
||||
;--------------------------------
|
||||
;Installer Sections
|
||||
|
||||
Section "-Core installation"
|
||||
;Use the entire tree produced by the INSTALL target. Keep the
|
||||
;list of directories here in sync with the RMDir commands below.
|
||||
SetOutPath "$INSTDIR"
|
||||
@CPACK_NSIS_FULL_INSTALL@
|
||||
|
||||
;Store installation folder
|
||||
WriteRegStr SHCTX "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "" $INSTDIR
|
||||
|
||||
;Create uninstaller
|
||||
WriteUninstaller "$INSTDIR\Uninstall.exe"
|
||||
Push "DisplayName"
|
||||
Push "@CPACK_NSIS_DISPLAY_NAME@"
|
||||
Call ConditionalAddToRegisty
|
||||
Push "DisplayVersion"
|
||||
Push "@CPACK_PACKAGE_VERSION@"
|
||||
Call ConditionalAddToRegisty
|
||||
Push "Publisher"
|
||||
Push "@CPACK_PACKAGE_VENDOR@"
|
||||
Call ConditionalAddToRegisty
|
||||
Push "UninstallString"
|
||||
Push "$INSTDIR\Uninstall.exe"
|
||||
Call ConditionalAddToRegisty
|
||||
Push "NoRepair"
|
||||
Push "1"
|
||||
Call ConditionalAddToRegisty
|
||||
|
||||
!ifdef CPACK_NSIS_ADD_REMOVE
|
||||
;Create add/remove functionality
|
||||
Push "ModifyPath"
|
||||
Push "$INSTDIR\AddRemove.exe"
|
||||
Call ConditionalAddToRegisty
|
||||
!else
|
||||
Push "NoModify"
|
||||
Push "1"
|
||||
Call ConditionalAddToRegisty
|
||||
!endif
|
||||
|
||||
; Optional registration
|
||||
Push "DisplayIcon"
|
||||
Push "$INSTDIR\@CPACK_NSIS_INSTALLED_ICON_NAME@"
|
||||
Call ConditionalAddToRegisty
|
||||
Push "HelpLink"
|
||||
Push "@CPACK_NSIS_HELP_LINK@"
|
||||
Call ConditionalAddToRegisty
|
||||
Push "URLInfoAbout"
|
||||
Push "@CPACK_NSIS_URL_INFO_ABOUT@"
|
||||
Call ConditionalAddToRegisty
|
||||
Push "Contact"
|
||||
Push "@CPACK_NSIS_CONTACT@"
|
||||
Call ConditionalAddToRegisty
|
||||
!insertmacro MUI_INSTALLOPTIONS_READ $INSTALL_DESKTOP "NSIS.InstallOptions.ini" "Field 5" "State"
|
||||
!insertmacro MUI_STARTMENU_WRITE_BEGIN Application
|
||||
|
||||
;Create shortcuts
|
||||
CreateDirectory "$SMPROGRAMS\$STARTMENU_FOLDER"
|
||||
@CPACK_NSIS_CREATE_ICONS@
|
||||
@CPACK_NSIS_CREATE_ICONS_EXTRA@
|
||||
CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\Uninstall.lnk" "$INSTDIR\Uninstall.exe"
|
||||
|
||||
;Read a value from an InstallOptions INI file
|
||||
!insertmacro MUI_INSTALLOPTIONS_READ $DO_NOT_ADD_TO_PATH "NSIS.InstallOptions.ini" "Field 2" "State"
|
||||
!insertmacro MUI_INSTALLOPTIONS_READ $ADD_TO_PATH_ALL_USERS "NSIS.InstallOptions.ini" "Field 3" "State"
|
||||
!insertmacro MUI_INSTALLOPTIONS_READ $ADD_TO_PATH_CURRENT_USER "NSIS.InstallOptions.ini" "Field 4" "State"
|
||||
|
||||
; Write special uninstall registry entries
|
||||
Push "StartMenu"
|
||||
Push "$STARTMENU_FOLDER"
|
||||
Call ConditionalAddToRegisty
|
||||
Push "DoNotAddToPath"
|
||||
Push "$DO_NOT_ADD_TO_PATH"
|
||||
Call ConditionalAddToRegisty
|
||||
Push "AddToPathAllUsers"
|
||||
Push "$ADD_TO_PATH_ALL_USERS"
|
||||
Call ConditionalAddToRegisty
|
||||
Push "AddToPathCurrentUser"
|
||||
Push "$ADD_TO_PATH_CURRENT_USER"
|
||||
Call ConditionalAddToRegisty
|
||||
Push "InstallToDesktop"
|
||||
Push "$INSTALL_DESKTOP"
|
||||
Call ConditionalAddToRegisty
|
||||
|
||||
!insertmacro MUI_STARTMENU_WRITE_END
|
||||
|
||||
@CPACK_NSIS_EXTRA_INSTALL_COMMANDS@
|
||||
|
||||
SectionEnd
|
||||
|
||||
Section "-Add to path"
|
||||
Push $INSTDIR\bin
|
||||
StrCmp "@CPACK_NSIS_MODIFY_PATH@" "ON" 0 doNotAddToPath
|
||||
StrCmp $DO_NOT_ADD_TO_PATH "1" doNotAddToPath 0
|
||||
Call AddToPath
|
||||
doNotAddToPath:
|
||||
SectionEnd
|
||||
|
||||
;--------------------------------
|
||||
; Create custom pages
|
||||
Function InstallOptionsPage
|
||||
!insertmacro MUI_HEADER_TEXT "Install Options" "Choose options for installing @CPACK_NSIS_PACKAGE_NAME@"
|
||||
!insertmacro MUI_INSTALLOPTIONS_DISPLAY "NSIS.InstallOptions.ini"
|
||||
|
||||
FunctionEnd
|
||||
|
||||
;--------------------------------
|
||||
; determine admin versus local install
|
||||
Function un.onInit
|
||||
|
||||
ClearErrors
|
||||
UserInfo::GetName
|
||||
IfErrors noLM
|
||||
Pop $0
|
||||
UserInfo::GetAccountType
|
||||
Pop $1
|
||||
StrCmp $1 "Admin" 0 +3
|
||||
SetShellVarContext all
|
||||
;MessageBox MB_OK 'User "$0" is in the Admin group'
|
||||
Goto done
|
||||
StrCmp $1 "Power" 0 +3
|
||||
SetShellVarContext all
|
||||
;MessageBox MB_OK 'User "$0" is in the Power Users group'
|
||||
Goto done
|
||||
|
||||
noLM:
|
||||
;Get installation folder from registry if available
|
||||
|
||||
done:
|
||||
|
||||
;Disable WoW64 redirection
|
||||
SetRegView 64
|
||||
|
||||
FunctionEnd
|
||||
|
||||
;--- Add/Remove callback functions: ---
|
||||
!macro SectionList MacroName
|
||||
;This macro used to perform operation on multiple sections.
|
||||
;List all of your components in following manner here.
|
||||
@CPACK_NSIS_COMPONENT_SECTION_LIST@
|
||||
!macroend
|
||||
|
||||
Section -FinishComponents
|
||||
;Removes unselected components and writes component status to registry
|
||||
!insertmacro SectionList "FinishSection"
|
||||
|
||||
!ifdef CPACK_NSIS_ADD_REMOVE
|
||||
; Get the name of the installer executable
|
||||
System::Call 'kernel32::GetModuleFileNameA(i 0, t .R0, i 1024) i r1'
|
||||
StrCpy $R3 $R0
|
||||
|
||||
; Strip off the last 13 characters, to see if we have AddRemove.exe
|
||||
StrLen $R1 $R0
|
||||
IntOp $R1 $R0 - 13
|
||||
StrCpy $R2 $R0 13 $R1
|
||||
StrCmp $R2 "AddRemove.exe" addremove_installed
|
||||
|
||||
; We're not running AddRemove.exe, so install it
|
||||
CopyFiles $R3 $INSTDIR\AddRemove.exe
|
||||
|
||||
addremove_installed:
|
||||
!endif
|
||||
SectionEnd
|
||||
;--- End of Add/Remove callback functions ---
|
||||
|
||||
;--------------------------------
|
||||
; Component dependencies
|
||||
Function .onSelChange
|
||||
!insertmacro SectionList MaybeSelectionChanged
|
||||
FunctionEnd
|
||||
|
||||
;--------------------------------
|
||||
;Uninstaller Section
|
||||
|
||||
Section "Uninstall"
|
||||
ReadRegStr $START_MENU SHCTX \
|
||||
"Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@ (x64)" "StartMenu"
|
||||
;MessageBox MB_OK "Start menu is in: $START_MENU"
|
||||
ReadRegStr $DO_NOT_ADD_TO_PATH SHCTX \
|
||||
"Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@ (x64)" "DoNotAddToPath"
|
||||
ReadRegStr $ADD_TO_PATH_ALL_USERS SHCTX \
|
||||
"Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@ (x64)" "AddToPathAllUsers"
|
||||
ReadRegStr $ADD_TO_PATH_CURRENT_USER SHCTX \
|
||||
"Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@ (x64)" "AddToPathCurrentUser"
|
||||
;MessageBox MB_OK "Add to path: $DO_NOT_ADD_TO_PATH all users: $ADD_TO_PATH_ALL_USERS"
|
||||
ReadRegStr $INSTALL_DESKTOP SHCTX \
|
||||
"Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@ (x64)" "InstallToDesktop"
|
||||
;MessageBox MB_OK "Install to desktop: $INSTALL_DESKTOP "
|
||||
|
||||
@CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS@
|
||||
|
||||
;Remove files we installed.
|
||||
;Keep the list of directories here in sync with the File commands above.
|
||||
@CPACK_NSIS_DELETE_FILES@
|
||||
@CPACK_NSIS_DELETE_DIRECTORIES@
|
||||
|
||||
!ifdef CPACK_NSIS_ADD_REMOVE
|
||||
;Remove the add/remove program
|
||||
Delete "$INSTDIR\AddRemove.exe"
|
||||
!endif
|
||||
|
||||
;Remove the uninstaller itself.
|
||||
Delete "$INSTDIR\Uninstall.exe"
|
||||
DeleteRegKey SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@ (x64)"
|
||||
|
||||
;Remove the installation directory if it is empty.
|
||||
RMDir "$INSTDIR"
|
||||
|
||||
; Remove the registry entries.
|
||||
DeleteRegKey SHCTX "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@"
|
||||
|
||||
; Removes all optional components
|
||||
!insertmacro SectionList "RemoveSection"
|
||||
|
||||
!insertmacro MUI_STARTMENU_GETFOLDER Application $MUI_TEMP
|
||||
|
||||
Delete "$SMPROGRAMS\$MUI_TEMP\Uninstall.lnk"
|
||||
@CPACK_NSIS_DELETE_ICONS@
|
||||
@CPACK_NSIS_DELETE_ICONS_EXTRA@
|
||||
|
||||
;Delete empty start menu parent diretories
|
||||
StrCpy $MUI_TEMP "$SMPROGRAMS\$MUI_TEMP"
|
||||
|
||||
startMenuDeleteLoop:
|
||||
ClearErrors
|
||||
RMDir $MUI_TEMP
|
||||
GetFullPathName $MUI_TEMP "$MUI_TEMP\.."
|
||||
|
||||
IfErrors startMenuDeleteLoopDone
|
||||
|
||||
StrCmp "$MUI_TEMP" "$SMPROGRAMS" startMenuDeleteLoopDone startMenuDeleteLoop
|
||||
startMenuDeleteLoopDone:
|
||||
|
||||
; If the user changed the shortcut, then untinstall may not work. This should
|
||||
; try to fix it.
|
||||
StrCpy $MUI_TEMP "$START_MENU"
|
||||
Delete "$SMPROGRAMS\$MUI_TEMP\Uninstall.lnk"
|
||||
@CPACK_NSIS_DELETE_ICONS_EXTRA@
|
||||
|
||||
;Delete empty start menu parent diretories
|
||||
StrCpy $MUI_TEMP "$SMPROGRAMS\$MUI_TEMP"
|
||||
|
||||
secondStartMenuDeleteLoop:
|
||||
ClearErrors
|
||||
RMDir $MUI_TEMP
|
||||
GetFullPathName $MUI_TEMP "$MUI_TEMP\.."
|
||||
|
||||
IfErrors secondStartMenuDeleteLoopDone
|
||||
|
||||
StrCmp "$MUI_TEMP" "$SMPROGRAMS" secondStartMenuDeleteLoopDone secondStartMenuDeleteLoop
|
||||
secondStartMenuDeleteLoopDone:
|
||||
|
||||
DeleteRegKey /ifempty SHCTX "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@"
|
||||
|
||||
Push $INSTDIR\bin
|
||||
StrCmp $DO_NOT_ADD_TO_PATH_ "1" doNotRemoveFromPath 0
|
||||
Call un.RemoveFromPath
|
||||
doNotRemoveFromPath:
|
||||
SectionEnd
|
||||
|
||||
;--------------------------------
|
||||
; determine admin versus local install
|
||||
; Is install for "AllUsers" or "JustMe"?
|
||||
; Default to "JustMe" - set to "AllUsers" if admin or on Win9x
|
||||
; This function is used for the very first "custom page" of the installer.
|
||||
; This custom page does not show up visibly, but it executes prior to the
|
||||
; first visible page and sets up $INSTDIR properly...
|
||||
; Choose different default installation folder based on SV_ALLUSERS...
|
||||
; "Program Files" for AllUsers, "My Documents" for JustMe...
|
||||
|
||||
Function .onInit
|
||||
; Reads components status for registry
|
||||
!insertmacro SectionList "InitSection"
|
||||
|
||||
; check to see if /D has been used to change
|
||||
; the install directory by comparing it to the
|
||||
; install directory that is expected to be the
|
||||
; default
|
||||
StrCpy $IS_DEFAULT_INSTALLDIR 0
|
||||
;StrCmp "$INSTDIR" "$PROGRAMFILES\@CPACK_PACKAGE_INSTALL_DIRECTORY@" 0 +2
|
||||
StrCmp "$INSTDIR" "$PROGRAMFILES64\@CPACK_PACKAGE_INSTALL_DIRECTORY@" 0 +2
|
||||
StrCpy $IS_DEFAULT_INSTALLDIR 1
|
||||
|
||||
StrCpy $SV_ALLUSERS "JustMe"
|
||||
; if default install dir then change the default
|
||||
; if it is installed for JustMe
|
||||
StrCmp "$IS_DEFAULT_INSTALLDIR" "1" 0 +2
|
||||
StrCpy $INSTDIR "$DOCUMENTS\@CPACK_PACKAGE_INSTALL_DIRECTORY@"
|
||||
|
||||
;Disable WoW64 redirection
|
||||
SetRegView 64
|
||||
|
||||
ClearErrors
|
||||
UserInfo::GetName
|
||||
IfErrors noLM
|
||||
Pop $0
|
||||
UserInfo::GetAccountType
|
||||
Pop $1
|
||||
StrCmp $1 "Admin" 0 +3
|
||||
SetShellVarContext all
|
||||
;MessageBox MB_OK 'User "$0" is in the Admin group'
|
||||
StrCpy $SV_ALLUSERS "AllUsers"
|
||||
Goto done
|
||||
StrCmp $1 "Power" 0 +3
|
||||
SetShellVarContext all
|
||||
;MessageBox MB_OK 'User "$0" is in the Power Users group'
|
||||
StrCpy $SV_ALLUSERS "AllUsers"
|
||||
Goto done
|
||||
|
||||
noLM:
|
||||
StrCpy $SV_ALLUSERS "AllUsers"
|
||||
;Get installation folder from registry if available
|
||||
|
||||
done:
|
||||
StrCmp $SV_ALLUSERS "AllUsers" 0 +3
|
||||
StrCmp "$IS_DEFAULT_INSTALLDIR" "1" 0 +2
|
||||
;StrCpy $INSTDIR "$PROGRAMFILES\@CPACK_PACKAGE_INSTALL_DIRECTORY@"
|
||||
StrCpy $INSTDIR "$PROGRAMFILES64\@CPACK_PACKAGE_INSTALL_DIRECTORY@"
|
||||
|
||||
StrCmp "@CPACK_NSIS_MODIFY_PATH@" "ON" 0 noOptionsPage
|
||||
!insertmacro MUI_INSTALLOPTIONS_EXTRACT "NSIS.InstallOptions.ini"
|
||||
|
||||
noOptionsPage:
|
||||
FunctionEnd
|
||||
34
3rd/libzmq/builds/cmake/ZeroMQConfig.cmake.in
Normal file
34
3rd/libzmq/builds/cmake/ZeroMQConfig.cmake.in
Normal file
@@ -0,0 +1,34 @@
|
||||
# ZeroMQ cmake module
|
||||
#
|
||||
# The following import targets are created
|
||||
#
|
||||
# ::
|
||||
#
|
||||
# libzmq-static
|
||||
# libzmq
|
||||
#
|
||||
# This module sets the following variables in your project::
|
||||
#
|
||||
# ZeroMQ_FOUND - true if ZeroMQ found on the system
|
||||
# ZeroMQ_INCLUDE_DIR - the directory containing ZeroMQ headers
|
||||
# ZeroMQ_LIBRARY -
|
||||
# ZeroMQ_STATIC_LIBRARY
|
||||
|
||||
@PACKAGE_INIT@
|
||||
|
||||
if(NOT TARGET libzmq AND NOT TARGET libzmq-static)
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
|
||||
|
||||
if (TARGET libzmq)
|
||||
get_target_property(@PROJECT_NAME@_INCLUDE_DIR libzmq INTERFACE_INCLUDE_DIRECTORIES)
|
||||
else ()
|
||||
get_target_property(@PROJECT_NAME@_INCLUDE_DIR libzmq-static INTERFACE_INCLUDE_DIRECTORIES)
|
||||
endif()
|
||||
|
||||
if (TARGET libzmq)
|
||||
get_target_property(@PROJECT_NAME@_LIBRARY libzmq LOCATION)
|
||||
endif()
|
||||
if (TARGET libzmq-static)
|
||||
get_target_property(@PROJECT_NAME@_STATIC_LIBRARY libzmq-static LOCATION)
|
||||
endif()
|
||||
endif()
|
||||
111
3rd/libzmq/builds/cmake/ci_build.sh
Normal file
111
3rd/libzmq/builds/cmake/ci_build.sh
Normal file
@@ -0,0 +1,111 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -x -e
|
||||
|
||||
cd ../..
|
||||
|
||||
# always install custom builds from dist
|
||||
# to make sure that `make dist` doesn't omit any files required to build & test
|
||||
if [ -z "$DO_CLANG_FORMAT_CHECK" -a -z "$CLANG_TIDY" ]; then
|
||||
./autogen.sh
|
||||
./configure
|
||||
make -j5 dist-gzip
|
||||
V=$(./version.sh)
|
||||
tar -xzf zeromq-$V.tar.gz
|
||||
cd zeromq-$V
|
||||
fi
|
||||
|
||||
mkdir tmp || true
|
||||
BUILD_PREFIX=$PWD/tmp
|
||||
|
||||
CONFIG_OPTS=()
|
||||
CONFIG_OPTS+=("CFLAGS=-I${BUILD_PREFIX}/include")
|
||||
CONFIG_OPTS+=("CPPFLAGS=-I${BUILD_PREFIX}/include")
|
||||
CONFIG_OPTS+=("CXXFLAGS=-I${BUILD_PREFIX}/include")
|
||||
CONFIG_OPTS+=("LDFLAGS=-L${BUILD_PREFIX}/lib")
|
||||
CONFIG_OPTS+=("PKG_CONFIG_PATH=${BUILD_PREFIX}/lib/pkgconfig")
|
||||
|
||||
CMAKE_OPTS=()
|
||||
CMAKE_OPTS+=("-DCMAKE_INSTALL_PREFIX:PATH=${BUILD_PREFIX}")
|
||||
CMAKE_OPTS+=("-DCMAKE_PREFIX_PATH:PATH=${BUILD_PREFIX}")
|
||||
CMAKE_OPTS+=("-DCMAKE_LIBRARY_PATH:PATH=${BUILD_PREFIX}/lib")
|
||||
CMAKE_OPTS+=("-DCMAKE_INCLUDE_PATH:PATH=${BUILD_PREFIX}/include")
|
||||
CMAKE_OPTS+=("-DENABLE_CAPSH=ON")
|
||||
|
||||
if [ "$CLANG_FORMAT" != "" ] ; then
|
||||
CMAKE_OPTS+=("-DCLANG_FORMAT=${CLANG_FORMAT}")
|
||||
fi
|
||||
|
||||
if [ -z $CURVE ]; then
|
||||
CMAKE_OPTS+=("-DENABLE_CURVE=OFF")
|
||||
elif [ $CURVE == "libsodium" ]; then
|
||||
CMAKE_OPTS+=("-DWITH_LIBSODIUM=ON")
|
||||
|
||||
if ! ((command -v dpkg-query >/dev/null 2>&1 && dpkg-query --list libsodium-dev >/dev/null 2>&1) || \
|
||||
(command -v brew >/dev/null 2>&1 && brew ls --versions libsodium >/dev/null 2>&1)); then
|
||||
git clone --depth 1 -b stable git://github.com/jedisct1/libsodium.git
|
||||
( cd libsodium; ./autogen.sh; ./configure --prefix=$BUILD_PREFIX; make install)
|
||||
fi
|
||||
fi
|
||||
|
||||
CMAKE_PREFIXES=()
|
||||
MAKE_PREFIXES=()
|
||||
PARALLEL_MAKE_OPT="-j5"
|
||||
if [ -n "$CLANG_TIDY" ] ; then
|
||||
CMAKE_OPTS+=("-DCMAKE_BUILD_TYPE=Debug") # do a debug build to avoid unused variable warnings with assertions, and to speed up build
|
||||
CMAKE_OPTS+=("-DCMAKE_CXX_CLANG_TIDY:STRING=${CLANG_TIDY}")
|
||||
if [ -n ${SONARCLOUD_BUILD_WRAPPER_PATH} ] ; then
|
||||
MAKE_PREFIXES+=("${SONARCLOUD_BUILD_WRAPPER_PATH}build-wrapper-linux-x86-64")
|
||||
MAKE_PREFIXES+=("--out-dir")
|
||||
MAKE_PREFIXES+=("${TRAVIS_BUILD_DIR}/bw-output")
|
||||
|
||||
fi
|
||||
CMAKE_PREFIXES+=("scan-build-10")
|
||||
MAKE_PREFIXES+=("scan-build-10")
|
||||
MAKE_PREFIXES+=("-plist-html")
|
||||
SCAN_BUILD_OUTPUT="$(pwd)/scan-build-report"
|
||||
MAKE_PREFIXES+=("-o ${SCAN_BUILD_OUTPUT}")
|
||||
# TODO this does not work with sonarcloud.io as it misses the sonar-cxx plugin
|
||||
#MAKE_PREFIXES+=("-plist")
|
||||
IFS="/" read -ra GITHUB_USER <<< "${TRAVIS_REPO_SLUG}"
|
||||
PARALLEL_MAKE_OPT=""
|
||||
fi
|
||||
|
||||
# Build, check, and install from local source
|
||||
mkdir build_cmake
|
||||
cd build_cmake
|
||||
if [ "$DO_CLANG_FORMAT_CHECK" = "1" ] ; then
|
||||
if ! ( PKG_CONFIG_PATH=${BUILD_PREFIX}/lib/pkgconfig cmake "${CMAKE_OPTS[@]}" .. && make clang-format-check) ; then
|
||||
make clang-format-diff
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
if [ -n "$CLANG_TIDY" ] ; then
|
||||
${CLANG_TIDY} -explain-config
|
||||
fi
|
||||
|
||||
export CTEST_OUTPUT_ON_FAILURE=1
|
||||
PKG_CONFIG_PATH=${BUILD_PREFIX}/lib/pkgconfig ${CMAKE_PREFIXES[@]} cmake "${CMAKE_OPTS[@]}" ..
|
||||
${MAKE_PREFIXES[@]} make ${PARALLEL_MAKE_OPT} all VERBOSE=1 | tee clang-tidy-report
|
||||
|
||||
if [ -n "${SONAR_SCANNER_CLI_PATH}" ] ; then
|
||||
find ${SCAN_BUILD_OUTPUT} || echo "WARNING: ${SCAN_BUILD_OUTPUT} does not exist"
|
||||
|
||||
${SONAR_SCANNER_CLI_PATH}sonar-scanner \
|
||||
-Dsonar.projectKey=${GITHUB_USER}-libzmq \
|
||||
-Dsonar.organization=${GITHUB_USER}-github \
|
||||
-Dsonar.projectBaseDir=.. \
|
||||
-Dsonar.sources=${TRAVIS_BUILD_DIR}/include,${TRAVIS_BUILD_DIR}/src,${TRAVIS_BUILD_DIR}/tests,${TRAVIS_BUILD_DIR}/unittests \
|
||||
-Dsonar.cfamily.build-wrapper-output=${TRAVIS_BUILD_DIR}/bw-output \
|
||||
-Dsonar.host.url=https://sonarcloud.io \
|
||||
-Dsonar.login=${SONARQUBE_TOKEN}
|
||||
|
||||
# TODO this does not work with sonarcloud.io as it misses the sonar-cxx plugin
|
||||
# -Dsonar.cxx.clangtidy.reportPath=clang-tidy-report \
|
||||
# -Dsonar.cxx.clangsa.reportPath=*.plist \
|
||||
|
||||
fi
|
||||
|
||||
make install
|
||||
make ${PARALLEL_MAKE_OPT} test ARGS="-V"
|
||||
fi
|
||||
14
3rd/libzmq/builds/cmake/clang-format-check.sh.in
Normal file
14
3rd/libzmq/builds/cmake/clang-format-check.sh.in
Normal file
@@ -0,0 +1,14 @@
|
||||
#!/bin/sh
|
||||
FAILED=0
|
||||
IFS=";"
|
||||
FILES="@ALL_SOURCE_FILES@"
|
||||
IDS=$(echo -en "\n\b")
|
||||
for FILE in $FILES
|
||||
do
|
||||
@CLANG_FORMAT@ -style=file -output-replacements-xml "$FILE" | grep "<replacement " >/dev/null &&
|
||||
{
|
||||
echo "$FILE is not correctly formatted"
|
||||
FAILED=1
|
||||
}
|
||||
done
|
||||
if [ "$FAILED" -eq "1" ] ; then exit 1 ; fi
|
||||
141
3rd/libzmq/builds/cmake/platform.hpp.in
Normal file
141
3rd/libzmq/builds/cmake/platform.hpp.in
Normal file
@@ -0,0 +1,141 @@
|
||||
#ifndef __ZMQ_PLATFORM_HPP_INCLUDED__
|
||||
#define __ZMQ_PLATFORM_HPP_INCLUDED__
|
||||
|
||||
#cmakedefine ZMQ_USE_CV_IMPL_STL11
|
||||
#cmakedefine ZMQ_USE_CV_IMPL_WIN32API
|
||||
#cmakedefine ZMQ_USE_CV_IMPL_PTHREADS
|
||||
#cmakedefine ZMQ_USE_CV_IMPL_NONE
|
||||
|
||||
#cmakedefine ZMQ_IOTHREAD_POLLER_USE_KQUEUE
|
||||
#cmakedefine ZMQ_IOTHREAD_POLLER_USE_EPOLL
|
||||
#cmakedefine ZMQ_IOTHREAD_POLLER_USE_EPOLL_CLOEXEC
|
||||
#cmakedefine ZMQ_IOTHREAD_POLLER_USE_DEVPOLL
|
||||
#cmakedefine ZMQ_IOTHREAD_POLLER_USE_POLL
|
||||
#cmakedefine ZMQ_IOTHREAD_POLLER_USE_SELECT
|
||||
|
||||
#cmakedefine ZMQ_POLL_BASED_ON_SELECT
|
||||
#cmakedefine ZMQ_POLL_BASED_ON_POLL
|
||||
|
||||
#cmakedefine ZMQ_CACHELINE_SIZE @ZMQ_CACHELINE_SIZE@
|
||||
|
||||
#cmakedefine ZMQ_FORCE_MUTEXES
|
||||
|
||||
#cmakedefine HAVE_FORK
|
||||
#cmakedefine HAVE_CLOCK_GETTIME
|
||||
#cmakedefine HAVE_GETHRTIME
|
||||
#cmakedefine HAVE_MKDTEMP
|
||||
#cmakedefine ZMQ_HAVE_UIO
|
||||
|
||||
#cmakedefine ZMQ_HAVE_NOEXCEPT
|
||||
|
||||
#cmakedefine ZMQ_HAVE_EVENTFD
|
||||
#cmakedefine ZMQ_HAVE_EVENTFD_CLOEXEC
|
||||
#cmakedefine ZMQ_HAVE_IFADDRS
|
||||
#cmakedefine ZMQ_HAVE_SO_BINDTODEVICE
|
||||
|
||||
#cmakedefine ZMQ_HAVE_SO_PEERCRED
|
||||
#cmakedefine ZMQ_HAVE_LOCAL_PEERCRED
|
||||
|
||||
#cmakedefine ZMQ_HAVE_O_CLOEXEC
|
||||
|
||||
#cmakedefine ZMQ_HAVE_SOCK_CLOEXEC
|
||||
#cmakedefine ZMQ_HAVE_SO_KEEPALIVE
|
||||
#cmakedefine ZMQ_HAVE_SO_PRIORITY
|
||||
#cmakedefine ZMQ_HAVE_TCP_KEEPCNT
|
||||
#cmakedefine ZMQ_HAVE_TCP_KEEPIDLE
|
||||
#cmakedefine ZMQ_HAVE_TCP_KEEPINTVL
|
||||
#cmakedefine ZMQ_HAVE_TCP_KEEPALIVE
|
||||
#cmakedefine ZMQ_HAVE_PTHREAD_SETNAME_1
|
||||
#cmakedefine ZMQ_HAVE_PTHREAD_SETNAME_2
|
||||
#cmakedefine ZMQ_HAVE_PTHREAD_SETNAME_3
|
||||
#cmakedefine ZMQ_HAVE_PTHREAD_SET_NAME
|
||||
#cmakedefine ZMQ_HAVE_PTHREAD_SET_AFFINITY
|
||||
#cmakedefine HAVE_ACCEPT4
|
||||
#cmakedefine HAVE_STRNLEN
|
||||
#cmakedefine ZMQ_HAVE_STRLCPY
|
||||
#cmakedefine ZMQ_HAVE_LIBBSD
|
||||
|
||||
#cmakedefine ZMQ_HAVE_IPC
|
||||
|
||||
#cmakedefine ZMQ_USE_BUILTIN_SHA1
|
||||
#cmakedefine ZMQ_USE_NSS
|
||||
#cmakedefine ZMQ_HAVE_WS
|
||||
#cmakedefine ZMQ_HAVE_WSS
|
||||
#cmakedefine ZMQ_HAVE_TIPC
|
||||
|
||||
#cmakedefine ZMQ_HAVE_OPENPGM
|
||||
#cmakedefine ZMQ_HAVE_NORM
|
||||
#cmakedefine ZMQ_MAKE_VALGRIND_HAPPY
|
||||
|
||||
#cmakedefine ZMQ_BUILD_DRAFT_API
|
||||
#cmakedefine ZMQ_HAVE_CURVE
|
||||
#cmakedefine ZMQ_USE_TWEETNACL
|
||||
#cmakedefine ZMQ_USE_LIBSODIUM
|
||||
#cmakedefine SODIUM_STATIC
|
||||
#cmakedefine ZMQ_USE_GNUTLS
|
||||
#cmakedefine ZMQ_USE_RADIX_TREE
|
||||
#cmakedefine HAVE_IF_NAMETOINDEX
|
||||
|
||||
#ifdef _AIX
|
||||
#define ZMQ_HAVE_AIX
|
||||
#endif
|
||||
|
||||
#if defined __ANDROID__
|
||||
#define ZMQ_HAVE_ANDROID
|
||||
#endif
|
||||
|
||||
#if defined __CYGWIN__
|
||||
#define ZMQ_HAVE_CYGWIN
|
||||
#endif
|
||||
|
||||
#if defined __MINGW32__
|
||||
#define ZMQ_HAVE_MINGW32
|
||||
#endif
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||
#define ZMQ_HAVE_FREEBSD
|
||||
#endif
|
||||
|
||||
#if defined(__DragonFly__)
|
||||
#define ZMQ_HAVE_FREEBSD
|
||||
#define ZMQ_HAVE_DRAGONFLY
|
||||
#endif
|
||||
|
||||
#if defined __hpux
|
||||
#define ZMQ_HAVE_HPUX
|
||||
#endif
|
||||
|
||||
#if defined __linux__
|
||||
#define ZMQ_HAVE_LINUX
|
||||
#endif
|
||||
|
||||
#if defined __NetBSD__
|
||||
#define ZMQ_HAVE_NETBSD
|
||||
#endif
|
||||
|
||||
#if defined __OpenBSD__
|
||||
#define ZMQ_HAVE_OPENBSD
|
||||
#endif
|
||||
|
||||
// TODO better move OS-specific defines to the automake files, and check for availability of IPC with an explicit test there
|
||||
#if defined __VMS
|
||||
#define ZMQ_HAVE_OPENVMS
|
||||
#undef ZMQ_HAVE_IPC
|
||||
#endif
|
||||
|
||||
#if defined __APPLE__
|
||||
#define ZMQ_HAVE_OSX
|
||||
#endif
|
||||
|
||||
#if defined __QNXNTO__
|
||||
#define ZMQ_HAVE_QNXNTO
|
||||
#endif
|
||||
|
||||
#if defined(sun) || defined(__sun)
|
||||
#define ZMQ_HAVE_SOLARIS
|
||||
#endif
|
||||
|
||||
#cmakedefine ZMQ_HAVE_WINDOWS
|
||||
#cmakedefine ZMQ_HAVE_WINDOWS_UWP
|
||||
|
||||
#endif
|
||||
26
3rd/libzmq/external/sha1/license.txt
vendored
Normal file
26
3rd/libzmq/external/sha1/license.txt
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of the project nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
336
3rd/libzmq/external/sha1/sha1.c
vendored
Normal file
336
3rd/libzmq/external/sha1/sha1.c
vendored
Normal file
@@ -0,0 +1,336 @@
|
||||
/*
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* FIPS pub 180-1: Secure Hash Algorithm (SHA-1)
|
||||
* based on: http://www.itl.nist.gov/fipspubs/fip180-1.htm
|
||||
* implemented by Jun-ichiro itojun Itoh <itojun@itojun.org>
|
||||
*/
|
||||
|
||||
#include "sha1.h"
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/* constant table */
|
||||
static uint32_t _K[] = {0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6};
|
||||
|
||||
#define K(t) _K[(t) / 20]
|
||||
|
||||
#define F0(b, c, d) (((b) & (c)) | ((~(b)) & (d)))
|
||||
#define F1(b, c, d) (((b) ^ (c)) ^ (d))
|
||||
#define F2(b, c, d) (((b) & (c)) | ((b) & (d)) | ((c) & (d)))
|
||||
#define F3(b, c, d) (((b) ^ (c)) ^ (d))
|
||||
|
||||
#define S(n, x) (((x) << (n)) | ((x) >> (32 - (n))))
|
||||
|
||||
#define H(n) (ctxt->h.b32[(n)])
|
||||
#define COUNT (ctxt->count)
|
||||
#define BCOUNT (ctxt->c.b64[0] / 8)
|
||||
#define W(n) (ctxt->m.b32[(n)])
|
||||
|
||||
#define PUTBYTE(x) \
|
||||
do { \
|
||||
ctxt->m.b8[(COUNT % 64)] = (x); \
|
||||
COUNT++; \
|
||||
COUNT %= 64; \
|
||||
ctxt->c.b64[0] += 8; \
|
||||
if (COUNT % 64 == 0) \
|
||||
sha1_step(ctxt); \
|
||||
} while (0)
|
||||
|
||||
#define PUTPAD(x) \
|
||||
do { \
|
||||
ctxt->m.b8[(COUNT % 64)] = (x); \
|
||||
COUNT++; \
|
||||
COUNT %= 64; \
|
||||
if (COUNT % 64 == 0) \
|
||||
sha1_step(ctxt); \
|
||||
} while (0)
|
||||
|
||||
static void sha1_step(struct sha1_ctxt *);
|
||||
|
||||
static void
|
||||
sha1_step(struct sha1_ctxt * ctxt)
|
||||
{
|
||||
uint32_t a,
|
||||
b,
|
||||
c,
|
||||
d,
|
||||
e;
|
||||
size_t t,
|
||||
s;
|
||||
uint32_t tmp;
|
||||
|
||||
#ifndef WORDS_BIGENDIAN
|
||||
struct sha1_ctxt tctxt;
|
||||
|
||||
memmove(&tctxt.m.b8[0], &ctxt->m.b8[0], 64);
|
||||
ctxt->m.b8[0] = tctxt.m.b8[3];
|
||||
ctxt->m.b8[1] = tctxt.m.b8[2];
|
||||
ctxt->m.b8[2] = tctxt.m.b8[1];
|
||||
ctxt->m.b8[3] = tctxt.m.b8[0];
|
||||
ctxt->m.b8[4] = tctxt.m.b8[7];
|
||||
ctxt->m.b8[5] = tctxt.m.b8[6];
|
||||
ctxt->m.b8[6] = tctxt.m.b8[5];
|
||||
ctxt->m.b8[7] = tctxt.m.b8[4];
|
||||
ctxt->m.b8[8] = tctxt.m.b8[11];
|
||||
ctxt->m.b8[9] = tctxt.m.b8[10];
|
||||
ctxt->m.b8[10] = tctxt.m.b8[9];
|
||||
ctxt->m.b8[11] = tctxt.m.b8[8];
|
||||
ctxt->m.b8[12] = tctxt.m.b8[15];
|
||||
ctxt->m.b8[13] = tctxt.m.b8[14];
|
||||
ctxt->m.b8[14] = tctxt.m.b8[13];
|
||||
ctxt->m.b8[15] = tctxt.m.b8[12];
|
||||
ctxt->m.b8[16] = tctxt.m.b8[19];
|
||||
ctxt->m.b8[17] = tctxt.m.b8[18];
|
||||
ctxt->m.b8[18] = tctxt.m.b8[17];
|
||||
ctxt->m.b8[19] = tctxt.m.b8[16];
|
||||
ctxt->m.b8[20] = tctxt.m.b8[23];
|
||||
ctxt->m.b8[21] = tctxt.m.b8[22];
|
||||
ctxt->m.b8[22] = tctxt.m.b8[21];
|
||||
ctxt->m.b8[23] = tctxt.m.b8[20];
|
||||
ctxt->m.b8[24] = tctxt.m.b8[27];
|
||||
ctxt->m.b8[25] = tctxt.m.b8[26];
|
||||
ctxt->m.b8[26] = tctxt.m.b8[25];
|
||||
ctxt->m.b8[27] = tctxt.m.b8[24];
|
||||
ctxt->m.b8[28] = tctxt.m.b8[31];
|
||||
ctxt->m.b8[29] = tctxt.m.b8[30];
|
||||
ctxt->m.b8[30] = tctxt.m.b8[29];
|
||||
ctxt->m.b8[31] = tctxt.m.b8[28];
|
||||
ctxt->m.b8[32] = tctxt.m.b8[35];
|
||||
ctxt->m.b8[33] = tctxt.m.b8[34];
|
||||
ctxt->m.b8[34] = tctxt.m.b8[33];
|
||||
ctxt->m.b8[35] = tctxt.m.b8[32];
|
||||
ctxt->m.b8[36] = tctxt.m.b8[39];
|
||||
ctxt->m.b8[37] = tctxt.m.b8[38];
|
||||
ctxt->m.b8[38] = tctxt.m.b8[37];
|
||||
ctxt->m.b8[39] = tctxt.m.b8[36];
|
||||
ctxt->m.b8[40] = tctxt.m.b8[43];
|
||||
ctxt->m.b8[41] = tctxt.m.b8[42];
|
||||
ctxt->m.b8[42] = tctxt.m.b8[41];
|
||||
ctxt->m.b8[43] = tctxt.m.b8[40];
|
||||
ctxt->m.b8[44] = tctxt.m.b8[47];
|
||||
ctxt->m.b8[45] = tctxt.m.b8[46];
|
||||
ctxt->m.b8[46] = tctxt.m.b8[45];
|
||||
ctxt->m.b8[47] = tctxt.m.b8[44];
|
||||
ctxt->m.b8[48] = tctxt.m.b8[51];
|
||||
ctxt->m.b8[49] = tctxt.m.b8[50];
|
||||
ctxt->m.b8[50] = tctxt.m.b8[49];
|
||||
ctxt->m.b8[51] = tctxt.m.b8[48];
|
||||
ctxt->m.b8[52] = tctxt.m.b8[55];
|
||||
ctxt->m.b8[53] = tctxt.m.b8[54];
|
||||
ctxt->m.b8[54] = tctxt.m.b8[53];
|
||||
ctxt->m.b8[55] = tctxt.m.b8[52];
|
||||
ctxt->m.b8[56] = tctxt.m.b8[59];
|
||||
ctxt->m.b8[57] = tctxt.m.b8[58];
|
||||
ctxt->m.b8[58] = tctxt.m.b8[57];
|
||||
ctxt->m.b8[59] = tctxt.m.b8[56];
|
||||
ctxt->m.b8[60] = tctxt.m.b8[63];
|
||||
ctxt->m.b8[61] = tctxt.m.b8[62];
|
||||
ctxt->m.b8[62] = tctxt.m.b8[61];
|
||||
ctxt->m.b8[63] = tctxt.m.b8[60];
|
||||
#endif
|
||||
|
||||
a = H(0);
|
||||
b = H(1);
|
||||
c = H(2);
|
||||
d = H(3);
|
||||
e = H(4);
|
||||
|
||||
for (t = 0; t < 20; t++)
|
||||
{
|
||||
s = t & 0x0f;
|
||||
if (t >= 16)
|
||||
W(s) = S(1, W((s + 13) & 0x0f) ^ W((s + 8) & 0x0f) ^ W((s + 2) & 0x0f) ^ W(s));
|
||||
tmp = S(5, a) + F0(b, c, d) + e + W(s) + K(t);
|
||||
e = d;
|
||||
d = c;
|
||||
c = S(30, b);
|
||||
b = a;
|
||||
a = tmp;
|
||||
}
|
||||
for (t = 20; t < 40; t++)
|
||||
{
|
||||
s = t & 0x0f;
|
||||
W(s) = S(1, W((s + 13) & 0x0f) ^ W((s + 8) & 0x0f) ^ W((s + 2) & 0x0f) ^ W(s));
|
||||
tmp = S(5, a) + F1(b, c, d) + e + W(s) + K(t);
|
||||
e = d;
|
||||
d = c;
|
||||
c = S(30, b);
|
||||
b = a;
|
||||
a = tmp;
|
||||
}
|
||||
for (t = 40; t < 60; t++)
|
||||
{
|
||||
s = t & 0x0f;
|
||||
W(s) = S(1, W((s + 13) & 0x0f) ^ W((s + 8) & 0x0f) ^ W((s + 2) & 0x0f) ^ W(s));
|
||||
tmp = S(5, a) + F2(b, c, d) + e + W(s) + K(t);
|
||||
e = d;
|
||||
d = c;
|
||||
c = S(30, b);
|
||||
b = a;
|
||||
a = tmp;
|
||||
}
|
||||
for (t = 60; t < 80; t++)
|
||||
{
|
||||
s = t & 0x0f;
|
||||
W(s) = S(1, W((s + 13) & 0x0f) ^ W((s + 8) & 0x0f) ^ W((s + 2) & 0x0f) ^ W(s));
|
||||
tmp = S(5, a) + F3(b, c, d) + e + W(s) + K(t);
|
||||
e = d;
|
||||
d = c;
|
||||
c = S(30, b);
|
||||
b = a;
|
||||
a = tmp;
|
||||
}
|
||||
|
||||
H(0) = H(0) + a;
|
||||
H(1) = H(1) + b;
|
||||
H(2) = H(2) + c;
|
||||
H(3) = H(3) + d;
|
||||
H(4) = H(4) + e;
|
||||
|
||||
memset(&ctxt->m.b8[0], 0, 64);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------*/
|
||||
|
||||
void
|
||||
sha1_init(struct sha1_ctxt * ctxt)
|
||||
{
|
||||
memset(ctxt, 0, sizeof(struct sha1_ctxt));
|
||||
H(0) = 0x67452301;
|
||||
H(1) = 0xefcdab89;
|
||||
H(2) = 0x98badcfe;
|
||||
H(3) = 0x10325476;
|
||||
H(4) = 0xc3d2e1f0;
|
||||
}
|
||||
|
||||
void
|
||||
sha1_pad(struct sha1_ctxt * ctxt)
|
||||
{
|
||||
size_t padlen; /* pad length in bytes */
|
||||
size_t padstart;
|
||||
|
||||
PUTPAD(0x80);
|
||||
|
||||
padstart = COUNT % 64;
|
||||
padlen = 64 - padstart;
|
||||
if (padlen < 8)
|
||||
{
|
||||
memset(&ctxt->m.b8[padstart], 0, padlen);
|
||||
COUNT += (uint8_t) padlen;
|
||||
COUNT %= 64;
|
||||
sha1_step(ctxt);
|
||||
padstart = COUNT % 64; /* should be 0 */
|
||||
padlen = 64 - padstart; /* should be 64 */
|
||||
}
|
||||
memset(&ctxt->m.b8[padstart], 0, padlen - 8);
|
||||
COUNT += ((uint8_t) padlen - 8);
|
||||
COUNT %= 64;
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
PUTPAD(ctxt->c.b8[0]);
|
||||
PUTPAD(ctxt->c.b8[1]);
|
||||
PUTPAD(ctxt->c.b8[2]);
|
||||
PUTPAD(ctxt->c.b8[3]);
|
||||
PUTPAD(ctxt->c.b8[4]);
|
||||
PUTPAD(ctxt->c.b8[5]);
|
||||
PUTPAD(ctxt->c.b8[6]);
|
||||
PUTPAD(ctxt->c.b8[7]);
|
||||
#else
|
||||
PUTPAD(ctxt->c.b8[7]);
|
||||
PUTPAD(ctxt->c.b8[6]);
|
||||
PUTPAD(ctxt->c.b8[5]);
|
||||
PUTPAD(ctxt->c.b8[4]);
|
||||
PUTPAD(ctxt->c.b8[3]);
|
||||
PUTPAD(ctxt->c.b8[2]);
|
||||
PUTPAD(ctxt->c.b8[1]);
|
||||
PUTPAD(ctxt->c.b8[0]);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
sha1_loop(struct sha1_ctxt * ctxt, const uint8_t *input0, size_t len)
|
||||
{
|
||||
const uint8_t *input;
|
||||
size_t gaplen;
|
||||
size_t gapstart;
|
||||
size_t off;
|
||||
size_t copysiz;
|
||||
|
||||
input = (const uint8_t *) input0;
|
||||
off = 0;
|
||||
|
||||
while (off < len)
|
||||
{
|
||||
gapstart = COUNT % 64;
|
||||
gaplen = 64 - gapstart;
|
||||
|
||||
copysiz = (gaplen < len - off) ? gaplen : len - off;
|
||||
memmove(&ctxt->m.b8[gapstart], &input[off], copysiz);
|
||||
COUNT += (uint8_t) copysiz;
|
||||
COUNT %= 64;
|
||||
ctxt->c.b64[0] += copysiz * 8;
|
||||
if (COUNT % 64 == 0)
|
||||
sha1_step(ctxt);
|
||||
off += copysiz;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sha1_result(struct sha1_ctxt * ctxt, uint8_t *digest0)
|
||||
{
|
||||
uint8_t *digest;
|
||||
|
||||
digest = (uint8_t *) digest0;
|
||||
sha1_pad(ctxt);
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
memmove(digest, &ctxt->h.b8[0], 20);
|
||||
#else
|
||||
digest[0] = ctxt->h.b8[3];
|
||||
digest[1] = ctxt->h.b8[2];
|
||||
digest[2] = ctxt->h.b8[1];
|
||||
digest[3] = ctxt->h.b8[0];
|
||||
digest[4] = ctxt->h.b8[7];
|
||||
digest[5] = ctxt->h.b8[6];
|
||||
digest[6] = ctxt->h.b8[5];
|
||||
digest[7] = ctxt->h.b8[4];
|
||||
digest[8] = ctxt->h.b8[11];
|
||||
digest[9] = ctxt->h.b8[10];
|
||||
digest[10] = ctxt->h.b8[9];
|
||||
digest[11] = ctxt->h.b8[8];
|
||||
digest[12] = ctxt->h.b8[15];
|
||||
digest[13] = ctxt->h.b8[14];
|
||||
digest[14] = ctxt->h.b8[13];
|
||||
digest[15] = ctxt->h.b8[12];
|
||||
digest[16] = ctxt->h.b8[19];
|
||||
digest[17] = ctxt->h.b8[18];
|
||||
digest[18] = ctxt->h.b8[17];
|
||||
digest[19] = ctxt->h.b8[16];
|
||||
#endif
|
||||
}
|
||||
87
3rd/libzmq/external/sha1/sha1.h
vendored
Normal file
87
3rd/libzmq/external/sha1/sha1.h
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
/* contrib/pgcrypto/sha1.h */
|
||||
/* $KAME: sha1.h,v 1.4 2000/02/22 14:01:18 itojun Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
/*
|
||||
* FIPS pub 180-1: Secure Hash Algorithm (SHA-1)
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* based on: http://www.itl.nist.gov/fipspubs/fip180-1.htm
|
||||
* implemented by Jun-ichiro itojun Itoh <itojun@itojun.org>
|
||||
*/
|
||||
|
||||
#ifndef _NETINET6_SHA1_H_
|
||||
#define _NETINET6_SHA1_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "../../src/stdint.hpp"
|
||||
|
||||
struct sha1_ctxt
|
||||
{
|
||||
union
|
||||
{
|
||||
uint8_t b8[20];
|
||||
uint32_t b32[5];
|
||||
} h;
|
||||
union
|
||||
{
|
||||
uint8_t b8[8];
|
||||
uint64_t b64[1];
|
||||
} c;
|
||||
union
|
||||
{
|
||||
uint8_t b8[64];
|
||||
uint32_t b32[16];
|
||||
} m;
|
||||
uint8_t count;
|
||||
};
|
||||
|
||||
void sha1_init(struct sha1_ctxt *);
|
||||
void sha1_pad(struct sha1_ctxt *);
|
||||
void sha1_loop(struct sha1_ctxt *, const uint8_t *, size_t);
|
||||
void sha1_result(struct sha1_ctxt *, uint8_t *);
|
||||
|
||||
// Compatibility with OpenSSL API
|
||||
#define SHA_DIGEST_LENGTH 20
|
||||
typedef struct sha1_ctxt SHA_CTX;
|
||||
|
||||
#define SHA1_Init(x) sha1_init((x))
|
||||
#define SHA1_Update(x, y, z) sha1_loop((x), (y), (z))
|
||||
#define SHA1_Final(x, y) sha1_result((y), (x))
|
||||
|
||||
#define SHA1_RESULTLEN (160/8)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _NETINET6_SHA1_H_ */
|
||||
21
3rd/libzmq/external/unity/license.txt
vendored
Normal file
21
3rd/libzmq/external/unity/license.txt
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) <year> 2007-14 Mike Karlesky, Mark VanderVoord, Greg Williams
|
||||
|
||||
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.
|
||||
1570
3rd/libzmq/external/unity/unity.c
vendored
Normal file
1570
3rd/libzmq/external/unity/unity.c
vendored
Normal file
@@ -0,0 +1,1570 @@
|
||||
/* =========================================================================
|
||||
Unity Project - A Test Framework for C
|
||||
Copyright (c) 2007-14 Mike Karlesky, Mark VanderVoord, Greg Williams
|
||||
[Released under MIT License. Please refer to license.txt for details]
|
||||
============================================================================ */
|
||||
|
||||
#define UNITY_INCLUDE_SETUP_STUBS
|
||||
#include "unity.h"
|
||||
#include <stddef.h>
|
||||
|
||||
/* If omitted from header, declare overrideable prototypes here so they're ready for use */
|
||||
#ifdef UNITY_OMIT_OUTPUT_CHAR_HEADER_DECLARATION
|
||||
void UNITY_OUTPUT_CHAR(int);
|
||||
#endif
|
||||
|
||||
/* Helpful macros for us to use here in Assert functions */
|
||||
#define UNITY_FAIL_AND_BAIL { Unity.CurrentTestFailed = 1; TEST_ABORT(); }
|
||||
#define UNITY_IGNORE_AND_BAIL { Unity.CurrentTestIgnored = 1; TEST_ABORT(); }
|
||||
#define RETURN_IF_FAIL_OR_IGNORE if (Unity.CurrentTestFailed || Unity.CurrentTestIgnored) return
|
||||
|
||||
struct UNITY_STORAGE_T Unity;
|
||||
|
||||
#ifdef UNITY_OUTPUT_COLOR
|
||||
static const char UnityStrOk[] = "\033[42mOK\033[00m";
|
||||
static const char UnityStrPass[] = "\033[42mPASS\033[00m";
|
||||
static const char UnityStrFail[] = "\033[41mFAIL\033[00m";
|
||||
static const char UnityStrIgnore[] = "\033[43mIGNORE\033[00m";
|
||||
#else
|
||||
static const char UnityStrOk[] = "OK";
|
||||
static const char UnityStrPass[] = "PASS";
|
||||
static const char UnityStrFail[] = "FAIL";
|
||||
static const char UnityStrIgnore[] = "IGNORE";
|
||||
#endif
|
||||
static const char UnityStrNull[] = "NULL";
|
||||
static const char UnityStrSpacer[] = ". ";
|
||||
static const char UnityStrExpected[] = " Expected ";
|
||||
static const char UnityStrWas[] = " Was ";
|
||||
static const char UnityStrGt[] = " to be greater than ";
|
||||
static const char UnityStrLt[] = " to be less than ";
|
||||
static const char UnityStrOrEqual[] = "or equal to ";
|
||||
static const char UnityStrElement[] = " Element ";
|
||||
static const char UnityStrByte[] = " Byte ";
|
||||
static const char UnityStrMemory[] = " Memory Mismatch.";
|
||||
static const char UnityStrDelta[] = " Values Not Within Delta ";
|
||||
static const char UnityStrPointless[] = " You Asked Me To Compare Nothing, Which Was Pointless.";
|
||||
static const char UnityStrNullPointerForExpected[] = " Expected pointer to be NULL";
|
||||
static const char UnityStrNullPointerForActual[] = " Actual pointer was NULL";
|
||||
#ifndef UNITY_EXCLUDE_FLOAT
|
||||
static const char UnityStrNot[] = "Not ";
|
||||
static const char UnityStrInf[] = "Infinity";
|
||||
static const char UnityStrNegInf[] = "Negative Infinity";
|
||||
static const char UnityStrNaN[] = "NaN";
|
||||
static const char UnityStrDet[] = "Determinate";
|
||||
static const char UnityStrInvalidFloatTrait[] = "Invalid Float Trait";
|
||||
#endif
|
||||
const char UnityStrErrFloat[] = "Unity Floating Point Disabled";
|
||||
const char UnityStrErrDouble[] = "Unity Double Precision Disabled";
|
||||
const char UnityStrErr64[] = "Unity 64-bit Support Disabled";
|
||||
static const char UnityStrBreaker[] = "-----------------------";
|
||||
static const char UnityStrResultsTests[] = " Tests ";
|
||||
static const char UnityStrResultsFailures[] = " Failures ";
|
||||
static const char UnityStrResultsIgnored[] = " Ignored ";
|
||||
static const char UnityStrDetail1Name[] = UNITY_DETAIL1_NAME " ";
|
||||
static const char UnityStrDetail2Name[] = " " UNITY_DETAIL2_NAME " ";
|
||||
|
||||
/*-----------------------------------------------
|
||||
* Pretty Printers & Test Result Output Handlers
|
||||
*-----------------------------------------------*/
|
||||
|
||||
void UnityPrint(const char* string)
|
||||
{
|
||||
const char* pch = string;
|
||||
|
||||
if (pch != NULL)
|
||||
{
|
||||
while (*pch)
|
||||
{
|
||||
/* printable characters plus CR & LF are printed */
|
||||
if ((*pch <= 126) && (*pch >= 32))
|
||||
{
|
||||
UNITY_OUTPUT_CHAR(*pch);
|
||||
}
|
||||
/* write escaped carriage returns */
|
||||
else if (*pch == 13)
|
||||
{
|
||||
UNITY_OUTPUT_CHAR('\\');
|
||||
UNITY_OUTPUT_CHAR('r');
|
||||
}
|
||||
/* write escaped line feeds */
|
||||
else if (*pch == 10)
|
||||
{
|
||||
UNITY_OUTPUT_CHAR('\\');
|
||||
UNITY_OUTPUT_CHAR('n');
|
||||
}
|
||||
#ifdef UNITY_OUTPUT_COLOR
|
||||
/* print ANSI escape code */
|
||||
else if (*pch == 27 && *(pch + 1) == '[')
|
||||
{
|
||||
while (*pch && *pch != 'm')
|
||||
{
|
||||
UNITY_OUTPUT_CHAR(*pch);
|
||||
pch++;
|
||||
}
|
||||
UNITY_OUTPUT_CHAR('m');
|
||||
}
|
||||
#endif
|
||||
/* unprintable characters are shown as codes */
|
||||
else
|
||||
{
|
||||
UNITY_OUTPUT_CHAR('\\');
|
||||
UNITY_OUTPUT_CHAR('x');
|
||||
UnityPrintNumberHex((UNITY_UINT)*pch, 2);
|
||||
}
|
||||
pch++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UnityPrintLen(const char* string, const UNITY_UINT32 length)
|
||||
{
|
||||
const char* pch = string;
|
||||
|
||||
if (pch != NULL)
|
||||
{
|
||||
while (*pch && (UNITY_UINT32)(pch - string) < length)
|
||||
{
|
||||
/* printable characters plus CR & LF are printed */
|
||||
if ((*pch <= 126) && (*pch >= 32))
|
||||
{
|
||||
UNITY_OUTPUT_CHAR(*pch);
|
||||
}
|
||||
/* write escaped carriage returns */
|
||||
else if (*pch == 13)
|
||||
{
|
||||
UNITY_OUTPUT_CHAR('\\');
|
||||
UNITY_OUTPUT_CHAR('r');
|
||||
}
|
||||
/* write escaped line feeds */
|
||||
else if (*pch == 10)
|
||||
{
|
||||
UNITY_OUTPUT_CHAR('\\');
|
||||
UNITY_OUTPUT_CHAR('n');
|
||||
}
|
||||
/* unprintable characters are shown as codes */
|
||||
else
|
||||
{
|
||||
UNITY_OUTPUT_CHAR('\\');
|
||||
UNITY_OUTPUT_CHAR('x');
|
||||
UnityPrintNumberHex((UNITY_UINT)*pch, 2);
|
||||
}
|
||||
pch++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------*/
|
||||
void UnityPrintNumberByStyle(const UNITY_INT number, const UNITY_DISPLAY_STYLE_T style)
|
||||
{
|
||||
if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT)
|
||||
{
|
||||
UnityPrintNumber(number);
|
||||
}
|
||||
else if ((style & UNITY_DISPLAY_RANGE_UINT) == UNITY_DISPLAY_RANGE_UINT)
|
||||
{
|
||||
UnityPrintNumberUnsigned((UNITY_UINT)number);
|
||||
}
|
||||
else
|
||||
{
|
||||
UNITY_OUTPUT_CHAR('0');
|
||||
UNITY_OUTPUT_CHAR('x');
|
||||
UnityPrintNumberHex((UNITY_UINT)number, (char)((style & 0xF) * 2));
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------*/
|
||||
void UnityPrintNumber(const UNITY_INT number_to_print)
|
||||
{
|
||||
UNITY_UINT number = (UNITY_UINT)number_to_print;
|
||||
|
||||
if (number_to_print < 0)
|
||||
{
|
||||
/* A negative number, including MIN negative */
|
||||
UNITY_OUTPUT_CHAR('-');
|
||||
number = (UNITY_UINT)(-number_to_print);
|
||||
}
|
||||
UnityPrintNumberUnsigned(number);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------
|
||||
* basically do an itoa using as little ram as possible */
|
||||
void UnityPrintNumberUnsigned(const UNITY_UINT number)
|
||||
{
|
||||
UNITY_UINT divisor = 1;
|
||||
|
||||
/* figure out initial divisor */
|
||||
while (number / divisor > 9)
|
||||
{
|
||||
divisor *= 10;
|
||||
}
|
||||
|
||||
/* now mod and print, then divide divisor */
|
||||
do
|
||||
{
|
||||
UNITY_OUTPUT_CHAR((char)('0' + (number / divisor % 10)));
|
||||
divisor /= 10;
|
||||
} while (divisor > 0);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------*/
|
||||
void UnityPrintNumberHex(const UNITY_UINT number, const char nibbles_to_print)
|
||||
{
|
||||
int nibble;
|
||||
char nibbles = nibbles_to_print;
|
||||
if ((unsigned)nibbles > (2 * sizeof(number)))
|
||||
nibbles = 2 * sizeof(number);
|
||||
|
||||
while (nibbles > 0)
|
||||
{
|
||||
nibbles--;
|
||||
nibble = (int)(number >> (nibbles * 4)) & 0x0F;
|
||||
if (nibble <= 9)
|
||||
{
|
||||
UNITY_OUTPUT_CHAR((char)('0' + nibble));
|
||||
}
|
||||
else
|
||||
{
|
||||
UNITY_OUTPUT_CHAR((char)('A' - 10 + nibble));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------*/
|
||||
void UnityPrintMask(const UNITY_UINT mask, const UNITY_UINT number)
|
||||
{
|
||||
UNITY_UINT current_bit = (UNITY_UINT)1 << (UNITY_INT_WIDTH - 1);
|
||||
UNITY_INT32 i;
|
||||
|
||||
for (i = 0; i < UNITY_INT_WIDTH; i++)
|
||||
{
|
||||
if (current_bit & mask)
|
||||
{
|
||||
if (current_bit & number)
|
||||
{
|
||||
UNITY_OUTPUT_CHAR('1');
|
||||
}
|
||||
else
|
||||
{
|
||||
UNITY_OUTPUT_CHAR('0');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UNITY_OUTPUT_CHAR('X');
|
||||
}
|
||||
current_bit = current_bit >> 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------*/
|
||||
#ifndef UNITY_EXCLUDE_FLOAT_PRINT
|
||||
/* This function prints a floating-point value in a format similar to
|
||||
* printf("%.6g"). It can work with either single- or double-precision,
|
||||
* but for simplicity, it prints only 6 significant digits in either case.
|
||||
* Printing more than 6 digits accurately is hard (at least in the single-
|
||||
* precision case) and isn't attempted here. */
|
||||
void UnityPrintFloat(const UNITY_DOUBLE input_number)
|
||||
{
|
||||
UNITY_DOUBLE number = input_number;
|
||||
|
||||
/* print minus sign (including for negative zero) */
|
||||
if (number < 0.0f || (number == 0.0f && 1.0f / number < 0.0f))
|
||||
{
|
||||
UNITY_OUTPUT_CHAR('-');
|
||||
number = -number;
|
||||
}
|
||||
|
||||
/* handle zero, NaN, and +/- infinity */
|
||||
if (number == 0.0f) UnityPrint("0");
|
||||
else if (isnan(number)) UnityPrint("nan");
|
||||
else if (isinf(number)) UnityPrint("inf");
|
||||
else
|
||||
{
|
||||
int exponent = 0;
|
||||
int decimals, digits;
|
||||
UNITY_INT32 n;
|
||||
char buf[16];
|
||||
|
||||
/* scale up or down by powers of 10 */
|
||||
while (number < 100000.0f / 1e6f) { number *= 1e6f; exponent -= 6; }
|
||||
while (number < 100000.0f) { number *= 10.0f; exponent--; }
|
||||
while (number > 1000000.0f * 1e6f) { number /= 1e6f; exponent += 6; }
|
||||
while (number > 1000000.0f) { number /= 10.0f; exponent++; }
|
||||
|
||||
/* round to nearest integer */
|
||||
n = ((UNITY_INT32)(number + number) + 1) / 2;
|
||||
if (n > 999999)
|
||||
{
|
||||
n = 100000;
|
||||
exponent++;
|
||||
}
|
||||
|
||||
/* determine where to place decimal point */
|
||||
decimals = (exponent <= 0 && exponent >= -9) ? -exponent : 5;
|
||||
exponent += decimals;
|
||||
|
||||
/* truncate trailing zeroes after decimal point */
|
||||
while (decimals > 0 && n % 10 == 0)
|
||||
{
|
||||
n /= 10;
|
||||
decimals--;
|
||||
}
|
||||
|
||||
/* build up buffer in reverse order */
|
||||
digits = 0;
|
||||
while (n != 0 || digits < decimals + 1)
|
||||
{
|
||||
buf[digits++] = (char)('0' + n % 10);
|
||||
n /= 10;
|
||||
}
|
||||
while (digits > 0)
|
||||
{
|
||||
if(digits == decimals) UNITY_OUTPUT_CHAR('.');
|
||||
UNITY_OUTPUT_CHAR(buf[--digits]);
|
||||
}
|
||||
|
||||
/* print exponent if needed */
|
||||
if (exponent != 0)
|
||||
{
|
||||
UNITY_OUTPUT_CHAR('e');
|
||||
|
||||
if(exponent < 0)
|
||||
{
|
||||
UNITY_OUTPUT_CHAR('-');
|
||||
exponent = -exponent;
|
||||
}
|
||||
else
|
||||
{
|
||||
UNITY_OUTPUT_CHAR('+');
|
||||
}
|
||||
|
||||
digits = 0;
|
||||
while (exponent != 0 || digits < 2)
|
||||
{
|
||||
buf[digits++] = (char)('0' + exponent % 10);
|
||||
exponent /= 10;
|
||||
}
|
||||
while (digits > 0)
|
||||
{
|
||||
UNITY_OUTPUT_CHAR(buf[--digits]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* ! UNITY_EXCLUDE_FLOAT_PRINT */
|
||||
|
||||
/*-----------------------------------------------*/
|
||||
static void UnityTestResultsBegin(const char* file, const UNITY_LINE_TYPE line)
|
||||
{
|
||||
UnityPrint(file);
|
||||
UNITY_OUTPUT_CHAR(':');
|
||||
UnityPrintNumber((UNITY_INT)line);
|
||||
UNITY_OUTPUT_CHAR(':');
|
||||
UnityPrint(Unity.CurrentTestName);
|
||||
UNITY_OUTPUT_CHAR(':');
|
||||
}
|
||||
|
||||
/*-----------------------------------------------*/
|
||||
static void UnityTestResultsFailBegin(const UNITY_LINE_TYPE line)
|
||||
{
|
||||
UnityTestResultsBegin(Unity.TestFile, line);
|
||||
UnityPrint(UnityStrFail);
|
||||
UNITY_OUTPUT_CHAR(':');
|
||||
}
|
||||
|
||||
/*-----------------------------------------------*/
|
||||
void UnityConcludeTest(void)
|
||||
{
|
||||
if (Unity.CurrentTestIgnored)
|
||||
{
|
||||
Unity.TestIgnores++;
|
||||
}
|
||||
else if (!Unity.CurrentTestFailed)
|
||||
{
|
||||
UnityTestResultsBegin(Unity.TestFile, Unity.CurrentTestLineNumber);
|
||||
UnityPrint(UnityStrPass);
|
||||
}
|
||||
else
|
||||
{
|
||||
Unity.TestFailures++;
|
||||
}
|
||||
|
||||
Unity.CurrentTestFailed = 0;
|
||||
Unity.CurrentTestIgnored = 0;
|
||||
UNITY_PRINT_EOL();
|
||||
UNITY_FLUSH_CALL();
|
||||
}
|
||||
|
||||
/*-----------------------------------------------*/
|
||||
static void UnityAddMsgIfSpecified(const char* msg)
|
||||
{
|
||||
if (msg)
|
||||
{
|
||||
UnityPrint(UnityStrSpacer);
|
||||
#ifndef UNITY_EXCLUDE_DETAILS
|
||||
if (Unity.CurrentDetail1)
|
||||
{
|
||||
UnityPrint(UnityStrDetail1Name);
|
||||
UnityPrint(Unity.CurrentDetail1);
|
||||
if (Unity.CurrentDetail2)
|
||||
{
|
||||
UnityPrint(UnityStrDetail2Name);
|
||||
UnityPrint(Unity.CurrentDetail2);
|
||||
}
|
||||
UnityPrint(UnityStrSpacer);
|
||||
}
|
||||
#endif
|
||||
UnityPrint(msg);
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------*/
|
||||
static void UnityPrintExpectedAndActualStrings(const char* expected, const char* actual)
|
||||
{
|
||||
UnityPrint(UnityStrExpected);
|
||||
if (expected != NULL)
|
||||
{
|
||||
UNITY_OUTPUT_CHAR('\'');
|
||||
UnityPrint(expected);
|
||||
UNITY_OUTPUT_CHAR('\'');
|
||||
}
|
||||
else
|
||||
{
|
||||
UnityPrint(UnityStrNull);
|
||||
}
|
||||
UnityPrint(UnityStrWas);
|
||||
if (actual != NULL)
|
||||
{
|
||||
UNITY_OUTPUT_CHAR('\'');
|
||||
UnityPrint(actual);
|
||||
UNITY_OUTPUT_CHAR('\'');
|
||||
}
|
||||
else
|
||||
{
|
||||
UnityPrint(UnityStrNull);
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------*/
|
||||
static void UnityPrintExpectedAndActualStringsLen(const char* expected,
|
||||
const char* actual,
|
||||
const UNITY_UINT32 length)
|
||||
{
|
||||
UnityPrint(UnityStrExpected);
|
||||
if (expected != NULL)
|
||||
{
|
||||
UNITY_OUTPUT_CHAR('\'');
|
||||
UnityPrintLen(expected, length);
|
||||
UNITY_OUTPUT_CHAR('\'');
|
||||
}
|
||||
else
|
||||
{
|
||||
UnityPrint(UnityStrNull);
|
||||
}
|
||||
UnityPrint(UnityStrWas);
|
||||
if (actual != NULL)
|
||||
{
|
||||
UNITY_OUTPUT_CHAR('\'');
|
||||
UnityPrintLen(actual, length);
|
||||
UNITY_OUTPUT_CHAR('\'');
|
||||
}
|
||||
else
|
||||
{
|
||||
UnityPrint(UnityStrNull);
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------
|
||||
* Assertion & Control Helpers
|
||||
*-----------------------------------------------*/
|
||||
|
||||
static int UnityIsOneArrayNull(UNITY_INTERNAL_PTR expected,
|
||||
UNITY_INTERNAL_PTR actual,
|
||||
const UNITY_LINE_TYPE lineNumber,
|
||||
const char* msg)
|
||||
{
|
||||
if (expected == actual) return 0; /* Both are NULL or same pointer */
|
||||
|
||||
/* print and return true if just expected is NULL */
|
||||
if (expected == NULL)
|
||||
{
|
||||
UnityTestResultsFailBegin(lineNumber);
|
||||
UnityPrint(UnityStrNullPointerForExpected);
|
||||
UnityAddMsgIfSpecified(msg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* print and return true if just actual is NULL */
|
||||
if (actual == NULL)
|
||||
{
|
||||
UnityTestResultsFailBegin(lineNumber);
|
||||
UnityPrint(UnityStrNullPointerForActual);
|
||||
UnityAddMsgIfSpecified(msg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0; /* return false if neither is NULL */
|
||||
}
|
||||
|
||||
/*-----------------------------------------------
|
||||
* Assertion Functions
|
||||
*-----------------------------------------------*/
|
||||
|
||||
void UnityAssertBits(const UNITY_INT mask,
|
||||
const UNITY_INT expected,
|
||||
const UNITY_INT actual,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber)
|
||||
{
|
||||
RETURN_IF_FAIL_OR_IGNORE;
|
||||
|
||||
if ((mask & expected) != (mask & actual))
|
||||
{
|
||||
UnityTestResultsFailBegin(lineNumber);
|
||||
UnityPrint(UnityStrExpected);
|
||||
UnityPrintMask((UNITY_UINT)mask, (UNITY_UINT)expected);
|
||||
UnityPrint(UnityStrWas);
|
||||
UnityPrintMask((UNITY_UINT)mask, (UNITY_UINT)actual);
|
||||
UnityAddMsgIfSpecified(msg);
|
||||
UNITY_FAIL_AND_BAIL;
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------*/
|
||||
void UnityAssertEqualNumber(const UNITY_INT expected,
|
||||
const UNITY_INT actual,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber,
|
||||
const UNITY_DISPLAY_STYLE_T style)
|
||||
{
|
||||
RETURN_IF_FAIL_OR_IGNORE;
|
||||
|
||||
if (expected != actual)
|
||||
{
|
||||
UnityTestResultsFailBegin(lineNumber);
|
||||
UnityPrint(UnityStrExpected);
|
||||
UnityPrintNumberByStyle(expected, style);
|
||||
UnityPrint(UnityStrWas);
|
||||
UnityPrintNumberByStyle(actual, style);
|
||||
UnityAddMsgIfSpecified(msg);
|
||||
UNITY_FAIL_AND_BAIL;
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------*/
|
||||
void UnityAssertGreaterOrLessOrEqualNumber(const UNITY_INT threshold,
|
||||
const UNITY_INT actual,
|
||||
const UNITY_COMPARISON_T compare,
|
||||
const char *msg,
|
||||
const UNITY_LINE_TYPE lineNumber,
|
||||
const UNITY_DISPLAY_STYLE_T style)
|
||||
{
|
||||
int failed = 0;
|
||||
RETURN_IF_FAIL_OR_IGNORE;
|
||||
|
||||
if (threshold == actual && compare & UNITY_EQUAL_TO) return;
|
||||
if (threshold == actual) failed = 1;
|
||||
|
||||
if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT)
|
||||
{
|
||||
if (actual > threshold && compare & UNITY_SMALLER_THAN) failed = 1;
|
||||
if (actual < threshold && compare & UNITY_GREATER_THAN) failed = 1;
|
||||
}
|
||||
else /* UINT or HEX */
|
||||
{
|
||||
if ((UNITY_UINT)actual > (UNITY_UINT)threshold && compare & UNITY_SMALLER_THAN) failed = 1;
|
||||
if ((UNITY_UINT)actual < (UNITY_UINT)threshold && compare & UNITY_GREATER_THAN) failed = 1;
|
||||
}
|
||||
|
||||
if (failed)
|
||||
{
|
||||
UnityTestResultsFailBegin(lineNumber);
|
||||
UnityPrint(UnityStrExpected);
|
||||
UnityPrintNumberByStyle(actual, style);
|
||||
if (compare & UNITY_GREATER_THAN) UnityPrint(UnityStrGt);
|
||||
if (compare & UNITY_SMALLER_THAN) UnityPrint(UnityStrLt);
|
||||
if (compare & UNITY_EQUAL_TO) UnityPrint(UnityStrOrEqual);
|
||||
UnityPrintNumberByStyle(threshold, style);
|
||||
UnityAddMsgIfSpecified(msg);
|
||||
UNITY_FAIL_AND_BAIL;
|
||||
}
|
||||
}
|
||||
|
||||
#define UnityPrintPointlessAndBail() \
|
||||
{ \
|
||||
UnityTestResultsFailBegin(lineNumber); \
|
||||
UnityPrint(UnityStrPointless); \
|
||||
UnityAddMsgIfSpecified(msg); \
|
||||
UNITY_FAIL_AND_BAIL; }
|
||||
|
||||
/*-----------------------------------------------*/
|
||||
void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected,
|
||||
UNITY_INTERNAL_PTR actual,
|
||||
const UNITY_UINT32 num_elements,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber,
|
||||
const UNITY_DISPLAY_STYLE_T style,
|
||||
const UNITY_FLAGS_T flags)
|
||||
{
|
||||
UNITY_UINT32 elements = num_elements;
|
||||
unsigned int length = style & 0xF;
|
||||
|
||||
RETURN_IF_FAIL_OR_IGNORE;
|
||||
|
||||
if (num_elements == 0)
|
||||
{
|
||||
UnityPrintPointlessAndBail();
|
||||
}
|
||||
|
||||
if (expected == actual) return; /* Both are NULL or same pointer */
|
||||
if (UnityIsOneArrayNull(expected, actual, lineNumber, msg))
|
||||
UNITY_FAIL_AND_BAIL;
|
||||
|
||||
while ((elements > 0) && elements--)
|
||||
{
|
||||
UNITY_INT expect_val;
|
||||
UNITY_INT actual_val;
|
||||
switch (length)
|
||||
{
|
||||
case 1:
|
||||
expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)expected;
|
||||
actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)actual;
|
||||
break;
|
||||
case 2:
|
||||
expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)expected;
|
||||
actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)actual;
|
||||
break;
|
||||
#ifdef UNITY_SUPPORT_64
|
||||
case 8:
|
||||
expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)expected;
|
||||
actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)actual;
|
||||
break;
|
||||
#endif
|
||||
default: /* length 4 bytes */
|
||||
expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)expected;
|
||||
actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)actual;
|
||||
length = 4;
|
||||
break;
|
||||
}
|
||||
|
||||
if (expect_val != actual_val)
|
||||
{
|
||||
if (style & UNITY_DISPLAY_RANGE_UINT && length < sizeof(expect_val))
|
||||
{ /* For UINT, remove sign extension (padding 1's) from signed type casts above */
|
||||
UNITY_INT mask = 1;
|
||||
mask = (mask << 8 * length) - 1;
|
||||
expect_val &= mask;
|
||||
actual_val &= mask;
|
||||
}
|
||||
UnityTestResultsFailBegin(lineNumber);
|
||||
UnityPrint(UnityStrElement);
|
||||
UnityPrintNumberUnsigned(num_elements - elements - 1);
|
||||
UnityPrint(UnityStrExpected);
|
||||
UnityPrintNumberByStyle(expect_val, style);
|
||||
UnityPrint(UnityStrWas);
|
||||
UnityPrintNumberByStyle(actual_val, style);
|
||||
UnityAddMsgIfSpecified(msg);
|
||||
UNITY_FAIL_AND_BAIL;
|
||||
}
|
||||
if (flags == UNITY_ARRAY_TO_ARRAY)
|
||||
{
|
||||
expected = (UNITY_INTERNAL_PTR)(length + (const char*)expected);
|
||||
}
|
||||
actual = (UNITY_INTERNAL_PTR)(length + (const char*)actual);
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------*/
|
||||
#ifndef UNITY_EXCLUDE_FLOAT
|
||||
/* Wrap this define in a function with variable types as float or double */
|
||||
#define UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff) \
|
||||
if (isinf(expected) && isinf(actual) && ((expected < 0) == (actual < 0))) return 1; \
|
||||
if (UNITY_NAN_CHECK) return 1; \
|
||||
diff = actual - expected; \
|
||||
if (diff < 0) diff = -diff; \
|
||||
if (delta < 0) delta = -delta; \
|
||||
return !(isnan(diff) || isinf(diff) || (diff > delta))
|
||||
/* This first part of this condition will catch any NaN or Infinite values */
|
||||
#ifndef UNITY_NAN_NOT_EQUAL_NAN
|
||||
#define UNITY_NAN_CHECK isnan(expected) && isnan(actual)
|
||||
#else
|
||||
#define UNITY_NAN_CHECK 0
|
||||
#endif
|
||||
|
||||
#ifndef UNITY_EXCLUDE_FLOAT_PRINT
|
||||
#define UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual) \
|
||||
{ \
|
||||
UnityPrint(UnityStrExpected); \
|
||||
UnityPrintFloat(expected); \
|
||||
UnityPrint(UnityStrWas); \
|
||||
UnityPrintFloat(actual); }
|
||||
#else
|
||||
#define UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual) \
|
||||
UnityPrint(UnityStrDelta)
|
||||
#endif /* UNITY_EXCLUDE_FLOAT_PRINT */
|
||||
|
||||
static int UnityFloatsWithin(UNITY_FLOAT delta, UNITY_FLOAT expected, UNITY_FLOAT actual)
|
||||
{
|
||||
UNITY_FLOAT diff;
|
||||
UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff);
|
||||
}
|
||||
|
||||
void UnityAssertEqualFloatArray(UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* expected,
|
||||
UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* actual,
|
||||
const UNITY_UINT32 num_elements,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber,
|
||||
const UNITY_FLAGS_T flags)
|
||||
{
|
||||
UNITY_UINT32 elements = num_elements;
|
||||
UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* ptr_expected = expected;
|
||||
UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* ptr_actual = actual;
|
||||
|
||||
RETURN_IF_FAIL_OR_IGNORE;
|
||||
|
||||
if (elements == 0)
|
||||
{
|
||||
UnityPrintPointlessAndBail();
|
||||
}
|
||||
|
||||
if (expected == actual) return; /* Both are NULL or same pointer */
|
||||
if (UnityIsOneArrayNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg))
|
||||
UNITY_FAIL_AND_BAIL;
|
||||
|
||||
while (elements--)
|
||||
{
|
||||
if (!UnityFloatsWithin(*ptr_expected * UNITY_FLOAT_PRECISION, *ptr_expected, *ptr_actual))
|
||||
{
|
||||
UnityTestResultsFailBegin(lineNumber);
|
||||
UnityPrint(UnityStrElement);
|
||||
UnityPrintNumberUnsigned(num_elements - elements - 1);
|
||||
UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT((UNITY_DOUBLE)*ptr_expected, (UNITY_DOUBLE)*ptr_actual);
|
||||
UnityAddMsgIfSpecified(msg);
|
||||
UNITY_FAIL_AND_BAIL;
|
||||
}
|
||||
if (flags == UNITY_ARRAY_TO_ARRAY)
|
||||
{
|
||||
ptr_expected++;
|
||||
}
|
||||
ptr_actual++;
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------*/
|
||||
void UnityAssertFloatsWithin(const UNITY_FLOAT delta,
|
||||
const UNITY_FLOAT expected,
|
||||
const UNITY_FLOAT actual,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber)
|
||||
{
|
||||
RETURN_IF_FAIL_OR_IGNORE;
|
||||
|
||||
|
||||
if (!UnityFloatsWithin(delta, expected, actual))
|
||||
{
|
||||
UnityTestResultsFailBegin(lineNumber);
|
||||
UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT((UNITY_DOUBLE)expected, (UNITY_DOUBLE)actual);
|
||||
UnityAddMsgIfSpecified(msg);
|
||||
UNITY_FAIL_AND_BAIL;
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------*/
|
||||
void UnityAssertFloatSpecial(const UNITY_FLOAT actual,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber,
|
||||
const UNITY_FLOAT_TRAIT_T style)
|
||||
{
|
||||
const char* trait_names[] = {UnityStrInf, UnityStrNegInf, UnityStrNaN, UnityStrDet};
|
||||
UNITY_INT should_be_trait = ((UNITY_INT)style & 1);
|
||||
UNITY_INT is_trait = !should_be_trait;
|
||||
UNITY_INT trait_index = (UNITY_INT)(style >> 1);
|
||||
|
||||
RETURN_IF_FAIL_OR_IGNORE;
|
||||
|
||||
switch (style)
|
||||
{
|
||||
case UNITY_FLOAT_IS_INF:
|
||||
case UNITY_FLOAT_IS_NOT_INF:
|
||||
is_trait = isinf(actual) && (actual > 0);
|
||||
break;
|
||||
case UNITY_FLOAT_IS_NEG_INF:
|
||||
case UNITY_FLOAT_IS_NOT_NEG_INF:
|
||||
is_trait = isinf(actual) && (actual < 0);
|
||||
break;
|
||||
|
||||
case UNITY_FLOAT_IS_NAN:
|
||||
case UNITY_FLOAT_IS_NOT_NAN:
|
||||
is_trait = isnan(actual) ? 1 : 0;
|
||||
break;
|
||||
|
||||
case UNITY_FLOAT_IS_DET: /* A determinate number is non infinite and not NaN. */
|
||||
case UNITY_FLOAT_IS_NOT_DET:
|
||||
is_trait = !isinf(actual) && !isnan(actual);
|
||||
break;
|
||||
|
||||
default:
|
||||
trait_index = 0;
|
||||
trait_names[0] = UnityStrInvalidFloatTrait;
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_trait != should_be_trait)
|
||||
{
|
||||
UnityTestResultsFailBegin(lineNumber);
|
||||
UnityPrint(UnityStrExpected);
|
||||
if (!should_be_trait)
|
||||
UnityPrint(UnityStrNot);
|
||||
UnityPrint(trait_names[trait_index]);
|
||||
UnityPrint(UnityStrWas);
|
||||
#ifndef UNITY_EXCLUDE_FLOAT_PRINT
|
||||
UnityPrintFloat((UNITY_DOUBLE)actual);
|
||||
#else
|
||||
if (should_be_trait)
|
||||
UnityPrint(UnityStrNot);
|
||||
UnityPrint(trait_names[trait_index]);
|
||||
#endif
|
||||
UnityAddMsgIfSpecified(msg);
|
||||
UNITY_FAIL_AND_BAIL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* not UNITY_EXCLUDE_FLOAT */
|
||||
|
||||
/*-----------------------------------------------*/
|
||||
#ifndef UNITY_EXCLUDE_DOUBLE
|
||||
static int UnityDoublesWithin(UNITY_DOUBLE delta, UNITY_DOUBLE expected, UNITY_DOUBLE actual)
|
||||
{
|
||||
UNITY_DOUBLE diff;
|
||||
UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff);
|
||||
}
|
||||
|
||||
void UnityAssertEqualDoubleArray(UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* expected,
|
||||
UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* actual,
|
||||
const UNITY_UINT32 num_elements,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber,
|
||||
const UNITY_FLAGS_T flags)
|
||||
{
|
||||
UNITY_UINT32 elements = num_elements;
|
||||
UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* ptr_expected = expected;
|
||||
UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* ptr_actual = actual;
|
||||
|
||||
RETURN_IF_FAIL_OR_IGNORE;
|
||||
|
||||
if (elements == 0)
|
||||
{
|
||||
UnityPrintPointlessAndBail();
|
||||
}
|
||||
|
||||
if (expected == actual) return; /* Both are NULL or same pointer */
|
||||
if (UnityIsOneArrayNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg))
|
||||
UNITY_FAIL_AND_BAIL;
|
||||
|
||||
while (elements--)
|
||||
{
|
||||
if (!UnityDoublesWithin(*ptr_expected * UNITY_DOUBLE_PRECISION, *ptr_expected, *ptr_actual))
|
||||
{
|
||||
UnityTestResultsFailBegin(lineNumber);
|
||||
UnityPrint(UnityStrElement);
|
||||
UnityPrintNumberUnsigned(num_elements - elements - 1);
|
||||
UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(*ptr_expected, *ptr_actual);
|
||||
UnityAddMsgIfSpecified(msg);
|
||||
UNITY_FAIL_AND_BAIL;
|
||||
}
|
||||
if (flags == UNITY_ARRAY_TO_ARRAY)
|
||||
{
|
||||
ptr_expected++;
|
||||
}
|
||||
ptr_actual++;
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------*/
|
||||
void UnityAssertDoublesWithin(const UNITY_DOUBLE delta,
|
||||
const UNITY_DOUBLE expected,
|
||||
const UNITY_DOUBLE actual,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber)
|
||||
{
|
||||
RETURN_IF_FAIL_OR_IGNORE;
|
||||
|
||||
if (!UnityDoublesWithin(delta, expected, actual))
|
||||
{
|
||||
UnityTestResultsFailBegin(lineNumber);
|
||||
UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual);
|
||||
UnityAddMsgIfSpecified(msg);
|
||||
UNITY_FAIL_AND_BAIL;
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------*/
|
||||
|
||||
void UnityAssertDoubleSpecial(const UNITY_DOUBLE actual,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber,
|
||||
const UNITY_FLOAT_TRAIT_T style)
|
||||
{
|
||||
const char* trait_names[] = {UnityStrInf, UnityStrNegInf, UnityStrNaN, UnityStrDet};
|
||||
UNITY_INT should_be_trait = ((UNITY_INT)style & 1);
|
||||
UNITY_INT is_trait = !should_be_trait;
|
||||
UNITY_INT trait_index = (UNITY_INT)(style >> 1);
|
||||
|
||||
RETURN_IF_FAIL_OR_IGNORE;
|
||||
|
||||
switch (style)
|
||||
{
|
||||
case UNITY_FLOAT_IS_INF:
|
||||
case UNITY_FLOAT_IS_NOT_INF:
|
||||
is_trait = isinf(actual) && (actual > 0);
|
||||
break;
|
||||
case UNITY_FLOAT_IS_NEG_INF:
|
||||
case UNITY_FLOAT_IS_NOT_NEG_INF:
|
||||
is_trait = isinf(actual) && (actual < 0);
|
||||
break;
|
||||
|
||||
case UNITY_FLOAT_IS_NAN:
|
||||
case UNITY_FLOAT_IS_NOT_NAN:
|
||||
is_trait = isnan(actual) ? 1 : 0;
|
||||
break;
|
||||
|
||||
case UNITY_FLOAT_IS_DET: /* A determinate number is non infinite and not NaN. */
|
||||
case UNITY_FLOAT_IS_NOT_DET:
|
||||
is_trait = !isinf(actual) && !isnan(actual);
|
||||
break;
|
||||
|
||||
default:
|
||||
trait_index = 0;
|
||||
trait_names[0] = UnityStrInvalidFloatTrait;
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_trait != should_be_trait)
|
||||
{
|
||||
UnityTestResultsFailBegin(lineNumber);
|
||||
UnityPrint(UnityStrExpected);
|
||||
if (!should_be_trait)
|
||||
UnityPrint(UnityStrNot);
|
||||
UnityPrint(trait_names[trait_index]);
|
||||
UnityPrint(UnityStrWas);
|
||||
#ifndef UNITY_EXCLUDE_FLOAT_PRINT
|
||||
UnityPrintFloat(actual);
|
||||
#else
|
||||
if (should_be_trait)
|
||||
UnityPrint(UnityStrNot);
|
||||
UnityPrint(trait_names[trait_index]);
|
||||
#endif
|
||||
UnityAddMsgIfSpecified(msg);
|
||||
UNITY_FAIL_AND_BAIL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* not UNITY_EXCLUDE_DOUBLE */
|
||||
|
||||
/*-----------------------------------------------*/
|
||||
void UnityAssertNumbersWithin(const UNITY_UINT delta,
|
||||
const UNITY_INT expected,
|
||||
const UNITY_INT actual,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber,
|
||||
const UNITY_DISPLAY_STYLE_T style)
|
||||
{
|
||||
RETURN_IF_FAIL_OR_IGNORE;
|
||||
|
||||
if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT)
|
||||
{
|
||||
if (actual > expected)
|
||||
Unity.CurrentTestFailed = (UNITY_UINT)((UNITY_UINT)(actual - expected) > delta);
|
||||
else
|
||||
Unity.CurrentTestFailed = (UNITY_UINT)((UNITY_UINT)(expected - actual) > delta);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((UNITY_UINT)actual > (UNITY_UINT)expected)
|
||||
Unity.CurrentTestFailed = (UNITY_UINT)((UNITY_UINT)(actual - expected) > delta);
|
||||
else
|
||||
Unity.CurrentTestFailed = (UNITY_UINT)((UNITY_UINT)(expected - actual) > delta);
|
||||
}
|
||||
|
||||
if (Unity.CurrentTestFailed)
|
||||
{
|
||||
UnityTestResultsFailBegin(lineNumber);
|
||||
UnityPrint(UnityStrDelta);
|
||||
UnityPrintNumberByStyle((UNITY_INT)delta, style);
|
||||
UnityPrint(UnityStrExpected);
|
||||
UnityPrintNumberByStyle(expected, style);
|
||||
UnityPrint(UnityStrWas);
|
||||
UnityPrintNumberByStyle(actual, style);
|
||||
UnityAddMsgIfSpecified(msg);
|
||||
UNITY_FAIL_AND_BAIL;
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------*/
|
||||
void UnityAssertEqualString(const char* expected,
|
||||
const char* actual,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber)
|
||||
{
|
||||
UNITY_UINT32 i;
|
||||
|
||||
RETURN_IF_FAIL_OR_IGNORE;
|
||||
|
||||
/* if both pointers not null compare the strings */
|
||||
if (expected && actual)
|
||||
{
|
||||
for (i = 0; expected[i] || actual[i]; i++)
|
||||
{
|
||||
if (expected[i] != actual[i])
|
||||
{
|
||||
Unity.CurrentTestFailed = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* handle case of one pointers being null (if both null, test should pass) */
|
||||
if (expected != actual)
|
||||
{
|
||||
Unity.CurrentTestFailed = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (Unity.CurrentTestFailed)
|
||||
{
|
||||
UnityTestResultsFailBegin(lineNumber);
|
||||
UnityPrintExpectedAndActualStrings(expected, actual);
|
||||
UnityAddMsgIfSpecified(msg);
|
||||
UNITY_FAIL_AND_BAIL;
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------*/
|
||||
void UnityAssertEqualStringLen(const char* expected,
|
||||
const char* actual,
|
||||
const UNITY_UINT32 length,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber)
|
||||
{
|
||||
UNITY_UINT32 i;
|
||||
|
||||
RETURN_IF_FAIL_OR_IGNORE;
|
||||
|
||||
/* if both pointers not null compare the strings */
|
||||
if (expected && actual)
|
||||
{
|
||||
for (i = 0; (i < length) && (expected[i] || actual[i]); i++)
|
||||
{
|
||||
if (expected[i] != actual[i])
|
||||
{
|
||||
Unity.CurrentTestFailed = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* handle case of one pointers being null (if both null, test should pass) */
|
||||
if (expected != actual)
|
||||
{
|
||||
Unity.CurrentTestFailed = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (Unity.CurrentTestFailed)
|
||||
{
|
||||
UnityTestResultsFailBegin(lineNumber);
|
||||
UnityPrintExpectedAndActualStringsLen(expected, actual, length);
|
||||
UnityAddMsgIfSpecified(msg);
|
||||
UNITY_FAIL_AND_BAIL;
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------*/
|
||||
void UnityAssertEqualStringArray(UNITY_INTERNAL_PTR expected,
|
||||
const char** actual,
|
||||
const UNITY_UINT32 num_elements,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber,
|
||||
const UNITY_FLAGS_T flags)
|
||||
{
|
||||
UNITY_UINT32 i = 0;
|
||||
UNITY_UINT32 j = 0;
|
||||
const char* expd = NULL;
|
||||
const char* act = NULL;
|
||||
|
||||
RETURN_IF_FAIL_OR_IGNORE;
|
||||
|
||||
/* if no elements, it's an error */
|
||||
if (num_elements == 0)
|
||||
{
|
||||
UnityPrintPointlessAndBail();
|
||||
}
|
||||
|
||||
if ((const void*)expected == (const void*)actual)
|
||||
{
|
||||
return; /* Both are NULL or same pointer */
|
||||
}
|
||||
|
||||
if (UnityIsOneArrayNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg))
|
||||
{
|
||||
UNITY_FAIL_AND_BAIL;
|
||||
}
|
||||
|
||||
if (flags != UNITY_ARRAY_TO_ARRAY)
|
||||
{
|
||||
expd = (const char*)expected;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
act = actual[j];
|
||||
if (flags == UNITY_ARRAY_TO_ARRAY)
|
||||
{
|
||||
expd = ((const char* const*)expected)[j];
|
||||
}
|
||||
|
||||
/* if both pointers not null compare the strings */
|
||||
if (expd && act)
|
||||
{
|
||||
for (i = 0; expd[i] || act[i]; i++)
|
||||
{
|
||||
if (expd[i] != act[i])
|
||||
{
|
||||
Unity.CurrentTestFailed = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* handle case of one pointers being null (if both null, test should pass) */
|
||||
if (expd != act)
|
||||
{
|
||||
Unity.CurrentTestFailed = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (Unity.CurrentTestFailed)
|
||||
{
|
||||
UnityTestResultsFailBegin(lineNumber);
|
||||
if (num_elements > 1)
|
||||
{
|
||||
UnityPrint(UnityStrElement);
|
||||
UnityPrintNumberUnsigned(j);
|
||||
}
|
||||
UnityPrintExpectedAndActualStrings(expd, act);
|
||||
UnityAddMsgIfSpecified(msg);
|
||||
UNITY_FAIL_AND_BAIL;
|
||||
}
|
||||
} while (++j < num_elements);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------*/
|
||||
void UnityAssertEqualMemory(UNITY_INTERNAL_PTR expected,
|
||||
UNITY_INTERNAL_PTR actual,
|
||||
const UNITY_UINT32 length,
|
||||
const UNITY_UINT32 num_elements,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber,
|
||||
const UNITY_FLAGS_T flags)
|
||||
{
|
||||
UNITY_PTR_ATTRIBUTE const unsigned char* ptr_exp = (UNITY_PTR_ATTRIBUTE const unsigned char*)expected;
|
||||
UNITY_PTR_ATTRIBUTE const unsigned char* ptr_act = (UNITY_PTR_ATTRIBUTE const unsigned char*)actual;
|
||||
UNITY_UINT32 elements = num_elements;
|
||||
UNITY_UINT32 bytes;
|
||||
|
||||
RETURN_IF_FAIL_OR_IGNORE;
|
||||
|
||||
if ((elements == 0) || (length == 0))
|
||||
{
|
||||
UnityPrintPointlessAndBail();
|
||||
}
|
||||
|
||||
if (expected == actual) return; /* Both are NULL or same pointer */
|
||||
if (UnityIsOneArrayNull(expected, actual, lineNumber, msg))
|
||||
UNITY_FAIL_AND_BAIL;
|
||||
|
||||
while (elements--)
|
||||
{
|
||||
bytes = length;
|
||||
while (bytes--)
|
||||
{
|
||||
if (*ptr_exp != *ptr_act)
|
||||
{
|
||||
UnityTestResultsFailBegin(lineNumber);
|
||||
UnityPrint(UnityStrMemory);
|
||||
if (num_elements > 1)
|
||||
{
|
||||
UnityPrint(UnityStrElement);
|
||||
UnityPrintNumberUnsigned(num_elements - elements - 1);
|
||||
}
|
||||
UnityPrint(UnityStrByte);
|
||||
UnityPrintNumberUnsigned(length - bytes - 1);
|
||||
UnityPrint(UnityStrExpected);
|
||||
UnityPrintNumberByStyle(*ptr_exp, UNITY_DISPLAY_STYLE_HEX8);
|
||||
UnityPrint(UnityStrWas);
|
||||
UnityPrintNumberByStyle(*ptr_act, UNITY_DISPLAY_STYLE_HEX8);
|
||||
UnityAddMsgIfSpecified(msg);
|
||||
UNITY_FAIL_AND_BAIL;
|
||||
}
|
||||
ptr_exp++;
|
||||
ptr_act++;
|
||||
}
|
||||
if (flags == UNITY_ARRAY_TO_VAL)
|
||||
{
|
||||
ptr_exp = (UNITY_PTR_ATTRIBUTE const unsigned char*)expected;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------*/
|
||||
|
||||
static union
|
||||
{
|
||||
UNITY_INT8 i8;
|
||||
UNITY_INT16 i16;
|
||||
UNITY_INT32 i32;
|
||||
#ifdef UNITY_SUPPORT_64
|
||||
UNITY_INT64 i64;
|
||||
#endif
|
||||
#ifndef UNITY_EXCLUDE_FLOAT
|
||||
float f;
|
||||
#endif
|
||||
#ifndef UNITY_EXCLUDE_DOUBLE
|
||||
double d;
|
||||
#endif
|
||||
} UnityQuickCompare;
|
||||
|
||||
UNITY_INTERNAL_PTR UnityNumToPtr(const UNITY_INT num, const UNITY_UINT8 size)
|
||||
{
|
||||
switch(size)
|
||||
{
|
||||
case 1:
|
||||
UnityQuickCompare.i8 = (UNITY_INT8)num;
|
||||
return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i8);
|
||||
|
||||
case 2:
|
||||
UnityQuickCompare.i16 = (UNITY_INT16)num;
|
||||
return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i16);
|
||||
|
||||
#ifdef UNITY_SUPPORT_64
|
||||
case 8:
|
||||
UnityQuickCompare.i64 = (UNITY_INT64)num;
|
||||
return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i64);
|
||||
#endif
|
||||
default: /* 4 bytes */
|
||||
UnityQuickCompare.i32 = (UNITY_INT32)num;
|
||||
return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i32);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef UNITY_EXCLUDE_FLOAT
|
||||
UNITY_INTERNAL_PTR UnityFloatToPtr(const float num)
|
||||
{
|
||||
UnityQuickCompare.f = num;
|
||||
return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.f);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef UNITY_EXCLUDE_DOUBLE
|
||||
UNITY_INTERNAL_PTR UnityDoubleToPtr(const double num)
|
||||
{
|
||||
UnityQuickCompare.d = num;
|
||||
return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.d);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------
|
||||
* Control Functions
|
||||
*-----------------------------------------------*/
|
||||
|
||||
void UnityFail(const char* msg, const UNITY_LINE_TYPE line)
|
||||
{
|
||||
RETURN_IF_FAIL_OR_IGNORE;
|
||||
|
||||
UnityTestResultsBegin(Unity.TestFile, line);
|
||||
UnityPrint(UnityStrFail);
|
||||
if (msg != NULL)
|
||||
{
|
||||
UNITY_OUTPUT_CHAR(':');
|
||||
|
||||
#ifndef UNITY_EXCLUDE_DETAILS
|
||||
if (Unity.CurrentDetail1)
|
||||
{
|
||||
UnityPrint(UnityStrDetail1Name);
|
||||
UnityPrint(Unity.CurrentDetail1);
|
||||
if (Unity.CurrentDetail2)
|
||||
{
|
||||
UnityPrint(UnityStrDetail2Name);
|
||||
UnityPrint(Unity.CurrentDetail2);
|
||||
}
|
||||
UnityPrint(UnityStrSpacer);
|
||||
}
|
||||
#endif
|
||||
if (msg[0] != ' ')
|
||||
{
|
||||
UNITY_OUTPUT_CHAR(' ');
|
||||
}
|
||||
UnityPrint(msg);
|
||||
}
|
||||
|
||||
UNITY_FAIL_AND_BAIL;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------*/
|
||||
void UnityIgnore(const char* msg, const UNITY_LINE_TYPE line)
|
||||
{
|
||||
RETURN_IF_FAIL_OR_IGNORE;
|
||||
|
||||
UnityTestResultsBegin(Unity.TestFile, line);
|
||||
UnityPrint(UnityStrIgnore);
|
||||
if (msg != NULL)
|
||||
{
|
||||
UNITY_OUTPUT_CHAR(':');
|
||||
UNITY_OUTPUT_CHAR(' ');
|
||||
UnityPrint(msg);
|
||||
}
|
||||
UNITY_IGNORE_AND_BAIL;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------*/
|
||||
void UnityDefaultTestRun(UnityTestFunction Func, const char* FuncName, const int FuncLineNum)
|
||||
{
|
||||
Unity.CurrentTestName = FuncName;
|
||||
Unity.CurrentTestLineNumber = (UNITY_LINE_TYPE)FuncLineNum;
|
||||
Unity.NumberOfTests++;
|
||||
UNITY_CLR_DETAILS();
|
||||
if (TEST_PROTECT())
|
||||
{
|
||||
setUp();
|
||||
Func();
|
||||
}
|
||||
if (TEST_PROTECT())
|
||||
{
|
||||
tearDown();
|
||||
}
|
||||
UnityConcludeTest();
|
||||
}
|
||||
|
||||
/*-----------------------------------------------*/
|
||||
void UnityBegin(const char* filename)
|
||||
{
|
||||
Unity.TestFile = filename;
|
||||
Unity.CurrentTestName = NULL;
|
||||
Unity.CurrentTestLineNumber = 0;
|
||||
Unity.NumberOfTests = 0;
|
||||
Unity.TestFailures = 0;
|
||||
Unity.TestIgnores = 0;
|
||||
Unity.CurrentTestFailed = 0;
|
||||
Unity.CurrentTestIgnored = 0;
|
||||
|
||||
UNITY_CLR_DETAILS();
|
||||
UNITY_OUTPUT_START();
|
||||
}
|
||||
|
||||
/*-----------------------------------------------*/
|
||||
int UnityEnd(void)
|
||||
{
|
||||
UNITY_PRINT_EOL();
|
||||
UnityPrint(UnityStrBreaker);
|
||||
UNITY_PRINT_EOL();
|
||||
UnityPrintNumber((UNITY_INT)(Unity.NumberOfTests));
|
||||
UnityPrint(UnityStrResultsTests);
|
||||
UnityPrintNumber((UNITY_INT)(Unity.TestFailures));
|
||||
UnityPrint(UnityStrResultsFailures);
|
||||
UnityPrintNumber((UNITY_INT)(Unity.TestIgnores));
|
||||
UnityPrint(UnityStrResultsIgnored);
|
||||
UNITY_PRINT_EOL();
|
||||
if (Unity.TestFailures == 0U)
|
||||
{
|
||||
UnityPrint(UnityStrOk);
|
||||
}
|
||||
else
|
||||
{
|
||||
UnityPrint(UnityStrFail);
|
||||
#ifdef UNITY_DIFFERENTIATE_FINAL_FAIL
|
||||
UNITY_OUTPUT_CHAR('E'); UNITY_OUTPUT_CHAR('D');
|
||||
#endif
|
||||
}
|
||||
UNITY_PRINT_EOL();
|
||||
UNITY_FLUSH_CALL();
|
||||
UNITY_OUTPUT_COMPLETE();
|
||||
return (int)(Unity.TestFailures);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------
|
||||
* Command Line Argument Support
|
||||
*-----------------------------------------------*/
|
||||
#ifdef UNITY_USE_COMMAND_LINE_ARGS
|
||||
|
||||
char* UnityOptionIncludeNamed = NULL;
|
||||
char* UnityOptionExcludeNamed = NULL;
|
||||
int UnityVerbosity = 1;
|
||||
|
||||
int UnityParseOptions(int argc, char** argv)
|
||||
{
|
||||
UnityOptionIncludeNamed = NULL;
|
||||
UnityOptionExcludeNamed = NULL;
|
||||
|
||||
for (int i = 1; i < argc; i++)
|
||||
{
|
||||
if (argv[i][0] == '-')
|
||||
{
|
||||
switch (argv[i][1])
|
||||
{
|
||||
case 'l': /* list tests */
|
||||
return -1;
|
||||
case 'n': /* include tests with name including this string */
|
||||
case 'f': /* an alias for -n */
|
||||
if (argv[i][2] == '=')
|
||||
UnityOptionIncludeNamed = &argv[i][3];
|
||||
else if (++i < argc)
|
||||
UnityOptionIncludeNamed = argv[i];
|
||||
else
|
||||
{
|
||||
UnityPrint("ERROR: No Test String to Include Matches For");
|
||||
UNITY_PRINT_EOL();
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 'q': /* quiet */
|
||||
UnityVerbosity = 0;
|
||||
break;
|
||||
case 'v': /* verbose */
|
||||
UnityVerbosity = 2;
|
||||
break;
|
||||
case 'x': /* exclude tests with name including this string */
|
||||
if (argv[i][2] == '=')
|
||||
UnityOptionExcludeNamed = &argv[i][3];
|
||||
else if (++i < argc)
|
||||
UnityOptionExcludeNamed = argv[i];
|
||||
else
|
||||
{
|
||||
UnityPrint("ERROR: No Test String to Exclude Matches For");
|
||||
UNITY_PRINT_EOL();
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
UnityPrint("ERROR: Unknown Option ");
|
||||
UNITY_OUTPUT_CHAR(argv[i][1]);
|
||||
UNITY_PRINT_EOL();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int IsStringInBiggerString(const char* longstring, const char* shortstring)
|
||||
{
|
||||
const char* lptr = longstring;
|
||||
const char* sptr = shortstring;
|
||||
const char* lnext = lptr;
|
||||
|
||||
if (*sptr == '*')
|
||||
return 1;
|
||||
|
||||
while (*lptr)
|
||||
{
|
||||
lnext = lptr + 1;
|
||||
|
||||
/* If they current bytes match, go on to the next bytes */
|
||||
while (*lptr && *sptr && (*lptr == *sptr))
|
||||
{
|
||||
lptr++;
|
||||
sptr++;
|
||||
|
||||
/* We're done if we match the entire string or up to a wildcard */
|
||||
if (*sptr == '*')
|
||||
return 1;
|
||||
if (*sptr == ',')
|
||||
return 1;
|
||||
if (*sptr == '"')
|
||||
return 1;
|
||||
if (*sptr == '\'')
|
||||
return 1;
|
||||
if (*sptr == ':')
|
||||
return 2;
|
||||
if (*sptr == 0)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Otherwise we start in the long pointer 1 character further and try again */
|
||||
lptr = lnext;
|
||||
sptr = shortstring;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int UnityStringArgumentMatches(const char* str)
|
||||
{
|
||||
int retval;
|
||||
const char* ptr1;
|
||||
const char* ptr2;
|
||||
const char* ptrf;
|
||||
|
||||
/* Go through the options and get the substrings for matching one at a time */
|
||||
ptr1 = str;
|
||||
while (ptr1[0] != 0)
|
||||
{
|
||||
if ((ptr1[0] == '"') || (ptr1[0] == '\''))
|
||||
ptr1++;
|
||||
|
||||
/* look for the start of the next partial */
|
||||
ptr2 = ptr1;
|
||||
ptrf = 0;
|
||||
do
|
||||
{
|
||||
ptr2++;
|
||||
if ((ptr2[0] == ':') && (ptr2[1] != 0) && (ptr2[0] != '\'') && (ptr2[0] != '"') && (ptr2[0] != ','))
|
||||
ptrf = &ptr2[1];
|
||||
} while ((ptr2[0] != 0) && (ptr2[0] != '\'') && (ptr2[0] != '"') && (ptr2[0] != ','));
|
||||
while ((ptr2[0] != 0) && ((ptr2[0] == ':') || (ptr2[0] == '\'') || (ptr2[0] == '"') || (ptr2[0] == ',')))
|
||||
ptr2++;
|
||||
|
||||
/* done if complete filename match */
|
||||
retval = IsStringInBiggerString(Unity.TestFile, ptr1);
|
||||
if (retval == 1)
|
||||
return retval;
|
||||
|
||||
/* done if testname match after filename partial match */
|
||||
if ((retval == 2) && (ptrf != 0))
|
||||
{
|
||||
if (IsStringInBiggerString(Unity.CurrentTestName, ptrf))
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* done if complete testname match */
|
||||
if (IsStringInBiggerString(Unity.CurrentTestName, ptr1) == 1)
|
||||
return 1;
|
||||
|
||||
ptr1 = ptr2;
|
||||
}
|
||||
|
||||
/* we couldn't find a match for any substrings */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int UnityTestMatches(void)
|
||||
{
|
||||
/* Check if this test name matches the included test pattern */
|
||||
int retval;
|
||||
if (UnityOptionIncludeNamed)
|
||||
{
|
||||
retval = UnityStringArgumentMatches(UnityOptionIncludeNamed);
|
||||
}
|
||||
else
|
||||
retval = 1;
|
||||
|
||||
/* Check if this test name matches the excluded test pattern */
|
||||
if (UnityOptionExcludeNamed)
|
||||
{
|
||||
if (UnityStringArgumentMatches(UnityOptionExcludeNamed))
|
||||
retval = 0;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
#endif /* UNITY_USE_COMMAND_LINE_ARGS */
|
||||
/*-----------------------------------------------*/
|
||||
503
3rd/libzmq/external/unity/unity.h
vendored
Normal file
503
3rd/libzmq/external/unity/unity.h
vendored
Normal file
@@ -0,0 +1,503 @@
|
||||
/* ==========================================
|
||||
Unity Project - A Test Framework for C
|
||||
Copyright (c) 2007-14 Mike Karlesky, Mark VanderVoord, Greg Williams
|
||||
[Released under MIT License. Please refer to license.txt for details]
|
||||
========================================== */
|
||||
|
||||
#ifndef UNITY_FRAMEWORK_H
|
||||
#define UNITY_FRAMEWORK_H
|
||||
#define UNITY
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "unity_internals.h"
|
||||
|
||||
/*-------------------------------------------------------
|
||||
* Test Setup / Teardown
|
||||
*-------------------------------------------------------*/
|
||||
|
||||
/* These functions are intended to be called before and after each test. */
|
||||
void setUp(void);
|
||||
void tearDown(void);
|
||||
|
||||
/* These functions are intended to be called at the beginning and end of an
|
||||
* entire test suite. suiteTearDown() is passed the number of tests that
|
||||
* failed, and its return value becomes the exit code of main(). */
|
||||
void suiteSetUp(void);
|
||||
int suiteTearDown(int num_failures);
|
||||
|
||||
/* If the compiler supports it, the following block provides stub
|
||||
* implementations of the above functions as weak symbols. Note that on
|
||||
* some platforms (MinGW for example), weak function implementations need
|
||||
* to be in the same translation unit they are called from. This can be
|
||||
* achieved by defining UNITY_INCLUDE_SETUP_STUBS before including unity.h. */
|
||||
#ifdef UNITY_INCLUDE_SETUP_STUBS
|
||||
#ifdef UNITY_WEAK_ATTRIBUTE
|
||||
UNITY_WEAK_ATTRIBUTE void setUp(void) { }
|
||||
UNITY_WEAK_ATTRIBUTE void tearDown(void) { }
|
||||
UNITY_WEAK_ATTRIBUTE void suiteSetUp(void) { }
|
||||
UNITY_WEAK_ATTRIBUTE int suiteTearDown(int num_failures) { return num_failures; }
|
||||
#elif defined(UNITY_WEAK_PRAGMA)
|
||||
#pragma weak setUp
|
||||
void setUp(void) { }
|
||||
#pragma weak tearDown
|
||||
void tearDown(void) { }
|
||||
#pragma weak suiteSetUp
|
||||
void suiteSetUp(void) { }
|
||||
#pragma weak suiteTearDown
|
||||
int suiteTearDown(int num_failures) { return num_failures; }
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------
|
||||
* Configuration Options
|
||||
*-------------------------------------------------------
|
||||
* All options described below should be passed as a compiler flag to all files using Unity. If you must add #defines, place them BEFORE the #include above.
|
||||
|
||||
* Integers/longs/pointers
|
||||
* - Unity attempts to automatically discover your integer sizes
|
||||
* - define UNITY_EXCLUDE_STDINT_H to stop attempting to look in <stdint.h>
|
||||
* - define UNITY_EXCLUDE_LIMITS_H to stop attempting to look in <limits.h>
|
||||
* - If you cannot use the automatic methods above, you can force Unity by using these options:
|
||||
* - define UNITY_SUPPORT_64
|
||||
* - set UNITY_INT_WIDTH
|
||||
* - set UNITY_LONG_WIDTH
|
||||
* - set UNITY_POINTER_WIDTH
|
||||
|
||||
* Floats
|
||||
* - define UNITY_EXCLUDE_FLOAT to disallow floating point comparisons
|
||||
* - define UNITY_FLOAT_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_FLOAT
|
||||
* - define UNITY_FLOAT_TYPE to specify doubles instead of single precision floats
|
||||
* - define UNITY_INCLUDE_DOUBLE to allow double floating point comparisons
|
||||
* - define UNITY_EXCLUDE_DOUBLE to disallow double floating point comparisons (default)
|
||||
* - define UNITY_DOUBLE_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_DOUBLE
|
||||
* - define UNITY_DOUBLE_TYPE to specify something other than double
|
||||
* - define UNITY_EXCLUDE_FLOAT_PRINT to trim binary size, won't print floating point values in errors
|
||||
|
||||
* Output
|
||||
* - by default, Unity prints to standard out with putchar. define UNITY_OUTPUT_CHAR(a) with a different function if desired
|
||||
* - define UNITY_DIFFERENTIATE_FINAL_FAIL to print FAILED (vs. FAIL) at test end summary - for automated search for failure
|
||||
|
||||
* Optimization
|
||||
* - by default, line numbers are stored in unsigned shorts. Define UNITY_LINE_TYPE with a different type if your files are huge
|
||||
* - by default, test and failure counters are unsigned shorts. Define UNITY_COUNTER_TYPE with a different type if you want to save space or have more than 65535 Tests.
|
||||
|
||||
* Test Cases
|
||||
* - define UNITY_SUPPORT_TEST_CASES to include the TEST_CASE macro, though really it's mostly about the runner generator script
|
||||
|
||||
* Parameterized Tests
|
||||
* - you'll want to create a define of TEST_CASE(...) which basically evaluates to nothing
|
||||
|
||||
* Tests with Arguments
|
||||
* - you'll want to define UNITY_USE_COMMAND_LINE_ARGS if you have the test runner passing arguments to Unity
|
||||
|
||||
*-------------------------------------------------------
|
||||
* Basic Fail and Ignore
|
||||
*-------------------------------------------------------*/
|
||||
|
||||
#define TEST_FAIL_MESSAGE(message) UNITY_TEST_FAIL(__LINE__, (message))
|
||||
#define TEST_FAIL() UNITY_TEST_FAIL(__LINE__, NULL)
|
||||
#define TEST_IGNORE_MESSAGE(message) UNITY_TEST_IGNORE(__LINE__, (message))
|
||||
#define TEST_IGNORE() UNITY_TEST_IGNORE(__LINE__, NULL)
|
||||
#define TEST_ONLY()
|
||||
|
||||
/* It is not necessary for you to call PASS. A PASS condition is assumed if nothing fails.
|
||||
* This method allows you to abort a test immediately with a PASS state, ignoring the remainder of the test. */
|
||||
#define TEST_PASS() TEST_ABORT()
|
||||
|
||||
/* This macro does nothing, but it is useful for build tools (like Ceedling) to make use of this to figure out
|
||||
* which files should be linked to in order to perform a test. Use it like TEST_FILE("sandwiches.c") */
|
||||
#define TEST_FILE(a)
|
||||
|
||||
/*-------------------------------------------------------
|
||||
* Test Asserts (simple)
|
||||
*-------------------------------------------------------*/
|
||||
|
||||
/* Boolean */
|
||||
#define TEST_ASSERT(condition) UNITY_TEST_ASSERT( (condition), __LINE__, " Expression Evaluated To FALSE")
|
||||
#define TEST_ASSERT_TRUE(condition) UNITY_TEST_ASSERT( (condition), __LINE__, " Expected TRUE Was FALSE")
|
||||
#define TEST_ASSERT_UNLESS(condition) UNITY_TEST_ASSERT( !(condition), __LINE__, " Expression Evaluated To TRUE")
|
||||
#define TEST_ASSERT_FALSE(condition) UNITY_TEST_ASSERT( !(condition), __LINE__, " Expected FALSE Was TRUE")
|
||||
#define TEST_ASSERT_NULL(pointer) UNITY_TEST_ASSERT_NULL( (pointer), __LINE__, " Expected NULL")
|
||||
#define TEST_ASSERT_NOT_NULL(pointer) UNITY_TEST_ASSERT_NOT_NULL((pointer), __LINE__, " Expected Non-NULL")
|
||||
|
||||
/* Integers (of all sizes) */
|
||||
#define TEST_ASSERT_EQUAL_INT(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_INT8(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT8((expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_INT16(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT16((expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_INT32(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT32((expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_INT64(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT64((expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, " Expected Not-Equal")
|
||||
#define TEST_ASSERT_EQUAL_UINT(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_UINT8(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT8( (expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_UINT16(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT16( (expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_UINT32(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT32( (expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_UINT64(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT64( (expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_HEX(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_HEX8(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX8( (expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_HEX16(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX16((expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_HEX32(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_HEX64(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX64((expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_BITS(mask, expected, actual) UNITY_TEST_ASSERT_BITS((mask), (expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_BITS_HIGH(mask, actual) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(-1), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_BITS_LOW(mask, actual) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(0), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_BIT_HIGH(bit, actual) UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(-1), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_BIT_LOW(bit, actual) UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(0), (actual), __LINE__, NULL)
|
||||
|
||||
/* Integer Greater Than/ Less Than (of all sizes) */
|
||||
#define TEST_ASSERT_GREATER_THAN(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_GREATER_THAN_INT(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_GREATER_THAN_INT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT8((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_GREATER_THAN_INT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT16((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_GREATER_THAN_INT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT32((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_GREATER_THAN_INT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT64((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_GREATER_THAN_UINT(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_GREATER_THAN_UINT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT8((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_GREATER_THAN_UINT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT16((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_GREATER_THAN_UINT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT32((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT64((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_GREATER_THAN_HEX8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX8((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_GREATER_THAN_HEX16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX16((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_GREATER_THAN_HEX32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX32((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX64((threshold), (actual), __LINE__, NULL)
|
||||
|
||||
#define TEST_ASSERT_LESS_THAN(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_LESS_THAN_INT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_LESS_THAN_INT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT8((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_LESS_THAN_INT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT16((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_LESS_THAN_INT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT32((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_LESS_THAN_INT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT64((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_LESS_THAN_UINT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_LESS_THAN_UINT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT8((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_LESS_THAN_UINT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT16((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_LESS_THAN_UINT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT32((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_LESS_THAN_UINT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT64((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_LESS_THAN_HEX8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX8((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_LESS_THAN_HEX16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX16((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_LESS_THAN_HEX32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX32((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_LESS_THAN_HEX64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX64((threshold), (actual), __LINE__, NULL)
|
||||
|
||||
#define TEST_ASSERT_GREATER_OR_EQUAL(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_GREATER_OR_EQUAL_INT(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_GREATER_OR_EQUAL_INT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_GREATER_OR_EQUAL_INT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_GREATER_OR_EQUAL_INT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_GREATER_OR_EQUAL_UINT(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_GREATER_OR_EQUAL_UINT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_GREATER_OR_EQUAL_UINT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_GREATER_OR_EQUAL_UINT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_GREATER_OR_EQUAL_HEX8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_GREATER_OR_EQUAL_HEX16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_GREATER_OR_EQUAL_HEX32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, NULL)
|
||||
|
||||
#define TEST_ASSERT_LESS_OR_EQUAL(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_LESS_OR_EQUAL_INT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_LESS_OR_EQUAL_INT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_LESS_OR_EQUAL_INT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_LESS_OR_EQUAL_INT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_LESS_OR_EQUAL_INT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_LESS_OR_EQUAL_UINT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_LESS_OR_EQUAL_UINT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_LESS_OR_EQUAL_UINT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_LESS_OR_EQUAL_UINT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_LESS_OR_EQUAL_UINT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_LESS_OR_EQUAL_HEX8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_LESS_OR_EQUAL_HEX16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_LESS_OR_EQUAL_HEX32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_LESS_OR_EQUAL_HEX64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, NULL)
|
||||
|
||||
/* Integer Ranges (of all sizes) */
|
||||
#define TEST_ASSERT_INT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT_WITHIN((delta), (expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_INT8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT8_WITHIN((delta), (expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_INT16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT16_WITHIN((delta), (expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_INT32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT32_WITHIN((delta), (expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_INT64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT64_WITHIN((delta), (expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_UINT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_UINT8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT8_WITHIN((delta), (expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_UINT16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT16_WITHIN((delta), (expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_UINT32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT32_WITHIN((delta), (expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_UINT64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT64_WITHIN((delta), (expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_HEX_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_HEX8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX8_WITHIN((delta), (expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_HEX16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX16_WITHIN((delta), (expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_HEX32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_HEX64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX64_WITHIN((delta), (expected), (actual), __LINE__, NULL)
|
||||
|
||||
/* Structs and Strings */
|
||||
#define TEST_ASSERT_EQUAL_PTR(expected, actual) UNITY_TEST_ASSERT_EQUAL_PTR((expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_STRING(expected, actual) UNITY_TEST_ASSERT_EQUAL_STRING((expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len) UNITY_TEST_ASSERT_EQUAL_STRING_LEN((expected), (actual), (len), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_MEMORY(expected, actual, len) UNITY_TEST_ASSERT_EQUAL_MEMORY((expected), (actual), (len), __LINE__, NULL)
|
||||
|
||||
/* Arrays */
|
||||
#define TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_HEX_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_STRING_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected, actual, len, num_elements) UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((expected), (actual), (len), (num_elements), __LINE__, NULL)
|
||||
|
||||
/* Arrays Compared To Single Value */
|
||||
#define TEST_ASSERT_EACH_EQUAL_INT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT((expected), (actual), (num_elements), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EACH_EQUAL_INT8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT8((expected), (actual), (num_elements), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EACH_EQUAL_INT16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT16((expected), (actual), (num_elements), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EACH_EQUAL_INT32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT32((expected), (actual), (num_elements), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EACH_EQUAL_INT64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT64((expected), (actual), (num_elements), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EACH_EQUAL_UINT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EACH_EQUAL_UINT8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT8((expected), (actual), (num_elements), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EACH_EQUAL_UINT16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT16((expected), (actual), (num_elements), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EACH_EQUAL_UINT32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT32((expected), (actual), (num_elements), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EACH_EQUAL_UINT64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT64((expected), (actual), (num_elements), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EACH_EQUAL_HEX(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EACH_EQUAL_HEX8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX8((expected), (actual), (num_elements), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EACH_EQUAL_HEX16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX16((expected), (actual), (num_elements), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EACH_EQUAL_HEX32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EACH_EQUAL_HEX64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX64((expected), (actual), (num_elements), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EACH_EQUAL_PTR(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_PTR((expected), (actual), (num_elements), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EACH_EQUAL_STRING(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_STRING((expected), (actual), (num_elements), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EACH_EQUAL_MEMORY(expected, actual, len, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY((expected), (actual), (len), (num_elements), __LINE__, NULL)
|
||||
|
||||
/* Floating Point (If Enabled) */
|
||||
#define TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_FLOAT(expected, actual) UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT((expected), (actual), (num_elements), __LINE__, NULL)
|
||||
#define TEST_ASSERT_FLOAT_IS_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_FLOAT_IS_NEG_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_FLOAT_IS_NAN(actual) UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_FLOAT_IS_DETERMINATE(actual) UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE((actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_FLOAT_IS_NOT_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF((actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF((actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_FLOAT_IS_NOT_NAN(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN((actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE((actual), __LINE__, NULL)
|
||||
|
||||
/* Double (If Enabled) */
|
||||
#define TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_DOUBLE(expected, actual) UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE((expected), (actual), (num_elements), __LINE__, NULL)
|
||||
#define TEST_ASSERT_DOUBLE_IS_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_DOUBLE_IS_NEG_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_DOUBLE_IS_NAN(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual) UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE((actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_DOUBLE_IS_NOT_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF((actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF((actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN((actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE((actual), __LINE__, NULL)
|
||||
|
||||
/*-------------------------------------------------------
|
||||
* Test Asserts (with additional messages)
|
||||
*-------------------------------------------------------*/
|
||||
|
||||
/* Boolean */
|
||||
#define TEST_ASSERT_MESSAGE(condition, message) UNITY_TEST_ASSERT( (condition), __LINE__, (message))
|
||||
#define TEST_ASSERT_TRUE_MESSAGE(condition, message) UNITY_TEST_ASSERT( (condition), __LINE__, (message))
|
||||
#define TEST_ASSERT_UNLESS_MESSAGE(condition, message) UNITY_TEST_ASSERT( !(condition), __LINE__, (message))
|
||||
#define TEST_ASSERT_FALSE_MESSAGE(condition, message) UNITY_TEST_ASSERT( !(condition), __LINE__, (message))
|
||||
#define TEST_ASSERT_NULL_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NULL( (pointer), __LINE__, (message))
|
||||
#define TEST_ASSERT_NOT_NULL_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NOT_NULL((pointer), __LINE__, (message))
|
||||
|
||||
/* Integers (of all sizes) */
|
||||
#define TEST_ASSERT_EQUAL_INT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_EQUAL_INT8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT8((expected), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_EQUAL_INT16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT16((expected), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_EQUAL_INT32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT32((expected), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_EQUAL_INT64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT64((expected), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, (message))
|
||||
#define TEST_ASSERT_EQUAL_UINT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_EQUAL_UINT8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT8( (expected), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_EQUAL_UINT16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT16( (expected), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_EQUAL_UINT32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT32( (expected), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_EQUAL_UINT64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT64( (expected), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_EQUAL_HEX_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_EQUAL_HEX8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX8( (expected), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_EQUAL_HEX16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX16((expected), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_EQUAL_HEX32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_EQUAL_HEX64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX64((expected), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_BITS_MESSAGE(mask, expected, actual, message) UNITY_TEST_ASSERT_BITS((mask), (expected), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_BITS_HIGH_MESSAGE(mask, actual, message) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(-1), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_BITS_LOW_MESSAGE(mask, actual, message) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(0), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_BIT_HIGH_MESSAGE(bit, actual, message) UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(-1), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_BIT_LOW_MESSAGE(bit, actual, message) UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(0), (actual), __LINE__, (message))
|
||||
|
||||
/* Integer Greater Than/ Less Than (of all sizes) */
|
||||
#define TEST_ASSERT_GREATER_THAN_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_GREATER_THAN_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_GREATER_THAN_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT8((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_GREATER_THAN_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT16((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_GREATER_THAN_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT32((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_GREATER_THAN_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT64((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_GREATER_THAN_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_GREATER_THAN_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT8((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_GREATER_THAN_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT16((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_GREATER_THAN_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT32((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_GREATER_THAN_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT64((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_GREATER_THAN_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX8((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_GREATER_THAN_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX16((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_GREATER_THAN_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX32((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_GREATER_THAN_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX64((threshold), (actual), __LINE__, (message))
|
||||
|
||||
#define TEST_ASSERT_LESS_THAN_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_LESS_THAN_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_LESS_THAN_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT8((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_LESS_THAN_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT16((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_LESS_THAN_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT32((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_LESS_THAN_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT64((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_LESS_THAN_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_LESS_THAN_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT8((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_LESS_THAN_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT16((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_LESS_THAN_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT32((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_LESS_THAN_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT64((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_LESS_THAN_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX8((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_LESS_THAN_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX16((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_LESS_THAN_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX32((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_LESS_THAN_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX64((threshold), (actual), __LINE__, (message))
|
||||
|
||||
#define TEST_ASSERT_GREATER_OR_EQUAL_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_GREATER_OR_EQUAL_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_GREATER_OR_EQUAL_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_GREATER_OR_EQUAL_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_GREATER_OR_EQUAL_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_GREATER_OR_EQUAL_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_GREATER_OR_EQUAL_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_GREATER_OR_EQUAL_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_GREATER_OR_EQUAL_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_GREATER_OR_EQUAL_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_GREATER_OR_EQUAL_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_GREATER_OR_EQUAL_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_GREATER_OR_EQUAL_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_GREATER_OR_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_GREATER_OR_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, (message))
|
||||
|
||||
#define TEST_ASSERT_LESS_OR_EQUAL_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_LESS_OR_EQUAL_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_LESS_OR_EQUAL_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_LESS_OR_EQUAL_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_LESS_OR_EQUAL_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_LESS_OR_EQUAL_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_LESS_OR_EQUAL_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_LESS_OR_EQUAL_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_LESS_OR_EQUAL_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_LESS_OR_EQUAL_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_LESS_OR_EQUAL_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_LESS_OR_EQUAL_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_LESS_OR_EQUAL_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_LESS_OR_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX32((threshold), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_LESS_OR_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX64((threshold), (actual), __LINE__, (message))
|
||||
|
||||
/* Integer Ranges (of all sizes) */
|
||||
#define TEST_ASSERT_INT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT_WITHIN((delta), (expected), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_INT8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT8_WITHIN((delta), (expected), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_INT16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT16_WITHIN((delta), (expected), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_INT32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT32_WITHIN((delta), (expected), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_INT64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT64_WITHIN((delta), (expected), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_UINT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_UINT8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT8_WITHIN((delta), (expected), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_UINT16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT16_WITHIN((delta), (expected), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_UINT32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT32_WITHIN((delta), (expected), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_UINT64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT64_WITHIN((delta), (expected), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_HEX_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_HEX8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX8_WITHIN((delta), (expected), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_HEX16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX16_WITHIN((delta), (expected), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_HEX32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_HEX64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX64_WITHIN((delta), (expected), (actual), __LINE__, (message))
|
||||
|
||||
/* Structs and Strings */
|
||||
#define TEST_ASSERT_EQUAL_PTR_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_PTR((expected), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_STRING((expected), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_EQUAL_STRING_LEN_MESSAGE(expected, actual, len, message) UNITY_TEST_ASSERT_EQUAL_STRING_LEN((expected), (actual), (len), __LINE__, (message))
|
||||
#define TEST_ASSERT_EQUAL_MEMORY_MESSAGE(expected, actual, len, message) UNITY_TEST_ASSERT_EQUAL_MEMORY((expected), (actual), (len), __LINE__, (message))
|
||||
|
||||
/* Arrays */
|
||||
#define TEST_ASSERT_EQUAL_INT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
|
||||
#define TEST_ASSERT_EQUAL_INT8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
|
||||
#define TEST_ASSERT_EQUAL_INT16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
|
||||
#define TEST_ASSERT_EQUAL_INT32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
|
||||
#define TEST_ASSERT_EQUAL_INT64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
|
||||
#define TEST_ASSERT_EQUAL_UINT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
|
||||
#define TEST_ASSERT_EQUAL_UINT8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
|
||||
#define TEST_ASSERT_EQUAL_UINT16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
|
||||
#define TEST_ASSERT_EQUAL_UINT32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
|
||||
#define TEST_ASSERT_EQUAL_UINT64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
|
||||
#define TEST_ASSERT_EQUAL_HEX_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
|
||||
#define TEST_ASSERT_EQUAL_HEX8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
|
||||
#define TEST_ASSERT_EQUAL_HEX16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
|
||||
#define TEST_ASSERT_EQUAL_HEX32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
|
||||
#define TEST_ASSERT_EQUAL_HEX64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
|
||||
#define TEST_ASSERT_EQUAL_PTR_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
|
||||
#define TEST_ASSERT_EQUAL_STRING_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
|
||||
#define TEST_ASSERT_EQUAL_MEMORY_ARRAY_MESSAGE(expected, actual, len, num_elements, message) UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((expected), (actual), (len), (num_elements), __LINE__, (message))
|
||||
|
||||
/* Arrays Compared To Single Value*/
|
||||
#define TEST_ASSERT_EACH_EQUAL_INT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT((expected), (actual), (num_elements), __LINE__, (message))
|
||||
#define TEST_ASSERT_EACH_EQUAL_INT8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT8((expected), (actual), (num_elements), __LINE__, (message))
|
||||
#define TEST_ASSERT_EACH_EQUAL_INT16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT16((expected), (actual), (num_elements), __LINE__, (message))
|
||||
#define TEST_ASSERT_EACH_EQUAL_INT32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT32((expected), (actual), (num_elements), __LINE__, (message))
|
||||
#define TEST_ASSERT_EACH_EQUAL_INT64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT64((expected), (actual), (num_elements), __LINE__, (message))
|
||||
#define TEST_ASSERT_EACH_EQUAL_UINT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, (message))
|
||||
#define TEST_ASSERT_EACH_EQUAL_UINT8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT8((expected), (actual), (num_elements), __LINE__, (message))
|
||||
#define TEST_ASSERT_EACH_EQUAL_UINT16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT16((expected), (actual), (num_elements), __LINE__, (message))
|
||||
#define TEST_ASSERT_EACH_EQUAL_UINT32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT32((expected), (actual), (num_elements), __LINE__, (message))
|
||||
#define TEST_ASSERT_EACH_EQUAL_UINT64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT64((expected), (actual), (num_elements), __LINE__, (message))
|
||||
#define TEST_ASSERT_EACH_EQUAL_HEX_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, (message))
|
||||
#define TEST_ASSERT_EACH_EQUAL_HEX8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX8((expected), (actual), (num_elements), __LINE__, (message))
|
||||
#define TEST_ASSERT_EACH_EQUAL_HEX16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX16((expected), (actual), (num_elements), __LINE__, (message))
|
||||
#define TEST_ASSERT_EACH_EQUAL_HEX32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, (message))
|
||||
#define TEST_ASSERT_EACH_EQUAL_HEX64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX64((expected), (actual), (num_elements), __LINE__, (message))
|
||||
#define TEST_ASSERT_EACH_EQUAL_PTR_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_PTR((expected), (actual), (num_elements), __LINE__, (message))
|
||||
#define TEST_ASSERT_EACH_EQUAL_STRING_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_STRING((expected), (actual), (num_elements), __LINE__, (message))
|
||||
#define TEST_ASSERT_EACH_EQUAL_MEMORY_MESSAGE(expected, actual, len, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY((expected), (actual), (len), (num_elements), __LINE__, (message))
|
||||
|
||||
/* Floating Point (If Enabled) */
|
||||
#define TEST_ASSERT_FLOAT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_EQUAL_FLOAT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_EQUAL_FLOAT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
|
||||
#define TEST_ASSERT_EACH_EQUAL_FLOAT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT((expected), (actual), (num_elements), __LINE__, (message))
|
||||
#define TEST_ASSERT_FLOAT_IS_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_FLOAT_IS_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_FLOAT_IS_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_FLOAT_IS_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE((actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_FLOAT_IS_NOT_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF((actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_FLOAT_IS_NOT_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF((actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_FLOAT_IS_NOT_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN((actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE((actual), __LINE__, (message))
|
||||
|
||||
/* Double (If Enabled) */
|
||||
#define TEST_ASSERT_DOUBLE_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_EQUAL_DOUBLE_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_EQUAL_DOUBLE_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
|
||||
#define TEST_ASSERT_EACH_EQUAL_DOUBLE_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE((expected), (actual), (num_elements), __LINE__, (message))
|
||||
#define TEST_ASSERT_DOUBLE_IS_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_DOUBLE_IS_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_DOUBLE_IS_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_DOUBLE_IS_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE((actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_DOUBLE_IS_NOT_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF((actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF((actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_DOUBLE_IS_NOT_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN((actual), __LINE__, (message))
|
||||
#define TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE((actual), __LINE__, (message))
|
||||
|
||||
/* end of UNITY_FRAMEWORK_H */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
872
3rd/libzmq/external/unity/unity_internals.h
vendored
Normal file
872
3rd/libzmq/external/unity/unity_internals.h
vendored
Normal file
@@ -0,0 +1,872 @@
|
||||
/* ==========================================
|
||||
Unity Project - A Test Framework for C
|
||||
Copyright (c) 2007-14 Mike Karlesky, Mark VanderVoord, Greg Williams
|
||||
[Released under MIT License. Please refer to license.txt for details]
|
||||
========================================== */
|
||||
|
||||
#ifndef UNITY_INTERNALS_H
|
||||
#define UNITY_INTERNALS_H
|
||||
|
||||
#ifdef UNITY_INCLUDE_CONFIG_H
|
||||
#include "unity_config.h"
|
||||
#endif
|
||||
|
||||
#ifndef UNITY_EXCLUDE_SETJMP_H
|
||||
#include <setjmp.h>
|
||||
#endif
|
||||
|
||||
#ifndef UNITY_EXCLUDE_MATH_H
|
||||
#include <math.h>
|
||||
#endif
|
||||
|
||||
/* Unity Attempts to Auto-Detect Integer Types
|
||||
* Attempt 1: UINT_MAX, ULONG_MAX in <limits.h>, or default to 32 bits
|
||||
* Attempt 2: UINTPTR_MAX in <stdint.h>, or default to same size as long
|
||||
* The user may override any of these derived constants:
|
||||
* UNITY_INT_WIDTH, UNITY_LONG_WIDTH, UNITY_POINTER_WIDTH */
|
||||
#ifndef UNITY_EXCLUDE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#ifndef UNITY_EXCLUDE_LIMITS_H
|
||||
#include <limits.h>
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------
|
||||
* Guess Widths If Not Specified
|
||||
*-------------------------------------------------------*/
|
||||
|
||||
/* Determine the size of an int, if not already specified.
|
||||
* We cannot use sizeof(int), because it is not yet defined
|
||||
* at this stage in the translation of the C program.
|
||||
* Therefore, infer it from UINT_MAX if possible. */
|
||||
#ifndef UNITY_INT_WIDTH
|
||||
#ifdef UINT_MAX
|
||||
#if (UINT_MAX == 0xFFFF)
|
||||
#define UNITY_INT_WIDTH (16)
|
||||
#elif (UINT_MAX == 0xFFFFFFFF)
|
||||
#define UNITY_INT_WIDTH (32)
|
||||
#elif (UINT_MAX == 0xFFFFFFFFFFFFFFFF)
|
||||
#define UNITY_INT_WIDTH (64)
|
||||
#endif
|
||||
#else /* Set to default */
|
||||
#define UNITY_INT_WIDTH (32)
|
||||
#endif /* UINT_MAX */
|
||||
#endif
|
||||
|
||||
/* Determine the size of a long, if not already specified. */
|
||||
#ifndef UNITY_LONG_WIDTH
|
||||
#ifdef ULONG_MAX
|
||||
#if (ULONG_MAX == 0xFFFF)
|
||||
#define UNITY_LONG_WIDTH (16)
|
||||
#elif (ULONG_MAX == 0xFFFFFFFF)
|
||||
#define UNITY_LONG_WIDTH (32)
|
||||
#elif (ULONG_MAX == 0xFFFFFFFFFFFFFFFF)
|
||||
#define UNITY_LONG_WIDTH (64)
|
||||
#endif
|
||||
#else /* Set to default */
|
||||
#define UNITY_LONG_WIDTH (32)
|
||||
#endif /* ULONG_MAX */
|
||||
#endif
|
||||
|
||||
/* Determine the size of a pointer, if not already specified. */
|
||||
#ifndef UNITY_POINTER_WIDTH
|
||||
#ifdef UINTPTR_MAX
|
||||
#if (UINTPTR_MAX <= 0xFFFF)
|
||||
#define UNITY_POINTER_WIDTH (16)
|
||||
#elif (UINTPTR_MAX <= 0xFFFFFFFF)
|
||||
#define UNITY_POINTER_WIDTH (32)
|
||||
#elif (UINTPTR_MAX <= 0xFFFFFFFFFFFFFFFF)
|
||||
#define UNITY_POINTER_WIDTH (64)
|
||||
#endif
|
||||
#else /* Set to default */
|
||||
#define UNITY_POINTER_WIDTH UNITY_LONG_WIDTH
|
||||
#endif /* UINTPTR_MAX */
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------
|
||||
* Int Support (Define types based on detected sizes)
|
||||
*-------------------------------------------------------*/
|
||||
|
||||
#if (UNITY_INT_WIDTH == 32)
|
||||
typedef unsigned char UNITY_UINT8;
|
||||
typedef unsigned short UNITY_UINT16;
|
||||
typedef unsigned int UNITY_UINT32;
|
||||
typedef signed char UNITY_INT8;
|
||||
typedef signed short UNITY_INT16;
|
||||
typedef signed int UNITY_INT32;
|
||||
#elif (UNITY_INT_WIDTH == 16)
|
||||
typedef unsigned char UNITY_UINT8;
|
||||
typedef unsigned int UNITY_UINT16;
|
||||
typedef unsigned long UNITY_UINT32;
|
||||
typedef signed char UNITY_INT8;
|
||||
typedef signed int UNITY_INT16;
|
||||
typedef signed long UNITY_INT32;
|
||||
#else
|
||||
#error Invalid UNITY_INT_WIDTH specified! (16 or 32 are supported)
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------
|
||||
* 64-bit Support
|
||||
*-------------------------------------------------------*/
|
||||
|
||||
#ifndef UNITY_SUPPORT_64
|
||||
#if UNITY_LONG_WIDTH == 64 || UNITY_POINTER_WIDTH == 64
|
||||
#define UNITY_SUPPORT_64
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef UNITY_SUPPORT_64
|
||||
/* No 64-bit Support */
|
||||
typedef UNITY_UINT32 UNITY_UINT;
|
||||
typedef UNITY_INT32 UNITY_INT;
|
||||
#else
|
||||
|
||||
/* 64-bit Support */
|
||||
#if (UNITY_LONG_WIDTH == 32)
|
||||
typedef unsigned long long UNITY_UINT64;
|
||||
typedef signed long long UNITY_INT64;
|
||||
#elif (UNITY_LONG_WIDTH == 64)
|
||||
typedef unsigned long UNITY_UINT64;
|
||||
typedef signed long UNITY_INT64;
|
||||
#else
|
||||
#error Invalid UNITY_LONG_WIDTH specified! (32 or 64 are supported)
|
||||
#endif
|
||||
typedef UNITY_UINT64 UNITY_UINT;
|
||||
typedef UNITY_INT64 UNITY_INT;
|
||||
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------
|
||||
* Pointer Support
|
||||
*-------------------------------------------------------*/
|
||||
|
||||
#if (UNITY_POINTER_WIDTH == 32)
|
||||
#define UNITY_PTR_TO_INT UNITY_INT32
|
||||
#define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX32
|
||||
#elif (UNITY_POINTER_WIDTH == 64)
|
||||
#define UNITY_PTR_TO_INT UNITY_INT64
|
||||
#define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX64
|
||||
#elif (UNITY_POINTER_WIDTH == 16)
|
||||
#define UNITY_PTR_TO_INT UNITY_INT16
|
||||
#define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX16
|
||||
#else
|
||||
#error Invalid UNITY_POINTER_WIDTH specified! (16, 32 or 64 are supported)
|
||||
#endif
|
||||
|
||||
#ifndef UNITY_PTR_ATTRIBUTE
|
||||
#define UNITY_PTR_ATTRIBUTE
|
||||
#endif
|
||||
|
||||
#ifndef UNITY_INTERNAL_PTR
|
||||
#define UNITY_INTERNAL_PTR UNITY_PTR_ATTRIBUTE const void*
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------
|
||||
* Float Support
|
||||
*-------------------------------------------------------*/
|
||||
|
||||
#ifdef UNITY_EXCLUDE_FLOAT
|
||||
|
||||
/* No Floating Point Support */
|
||||
#ifndef UNITY_EXCLUDE_DOUBLE
|
||||
#define UNITY_EXCLUDE_DOUBLE /* Remove double when excluding float support */
|
||||
#endif
|
||||
#ifndef UNITY_EXCLUDE_FLOAT_PRINT
|
||||
#define UNITY_EXCLUDE_FLOAT_PRINT
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
/* Floating Point Support */
|
||||
#ifndef UNITY_FLOAT_PRECISION
|
||||
#define UNITY_FLOAT_PRECISION (0.00001f)
|
||||
#endif
|
||||
#ifndef UNITY_FLOAT_TYPE
|
||||
#define UNITY_FLOAT_TYPE float
|
||||
#endif
|
||||
typedef UNITY_FLOAT_TYPE UNITY_FLOAT;
|
||||
|
||||
/* isinf & isnan macros should be provided by math.h */
|
||||
#ifndef isinf
|
||||
/* The value of Inf - Inf is NaN */
|
||||
#define isinf(n) (isnan((n) - (n)) && !isnan(n))
|
||||
#endif
|
||||
|
||||
#ifndef isnan
|
||||
/* NaN is the only floating point value that does NOT equal itself.
|
||||
* Therefore if n != n, then it is NaN. */
|
||||
#define isnan(n) ((n != n) ? 1 : 0)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------
|
||||
* Double Float Support
|
||||
*-------------------------------------------------------*/
|
||||
|
||||
/* unlike float, we DON'T include by default */
|
||||
#if defined(UNITY_EXCLUDE_DOUBLE) || !defined(UNITY_INCLUDE_DOUBLE)
|
||||
|
||||
/* No Floating Point Support */
|
||||
#ifndef UNITY_EXCLUDE_DOUBLE
|
||||
#define UNITY_EXCLUDE_DOUBLE
|
||||
#else
|
||||
#undef UNITY_INCLUDE_DOUBLE
|
||||
#endif
|
||||
|
||||
#ifndef UNITY_EXCLUDE_FLOAT
|
||||
#ifndef UNITY_DOUBLE_TYPE
|
||||
#define UNITY_DOUBLE_TYPE double
|
||||
#endif
|
||||
typedef UNITY_FLOAT UNITY_DOUBLE;
|
||||
/* For parameter in UnityPrintFloat(UNITY_DOUBLE), which aliases to double or float */
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
/* Double Floating Point Support */
|
||||
#ifndef UNITY_DOUBLE_PRECISION
|
||||
#define UNITY_DOUBLE_PRECISION (1e-12)
|
||||
#endif
|
||||
|
||||
#ifndef UNITY_DOUBLE_TYPE
|
||||
#define UNITY_DOUBLE_TYPE double
|
||||
#endif
|
||||
typedef UNITY_DOUBLE_TYPE UNITY_DOUBLE;
|
||||
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------
|
||||
* Output Method: stdout (DEFAULT)
|
||||
*-------------------------------------------------------*/
|
||||
#ifndef UNITY_OUTPUT_CHAR
|
||||
/* Default to using putchar, which is defined in stdio.h */
|
||||
#include <stdio.h>
|
||||
#define UNITY_OUTPUT_CHAR(a) (void)putchar(a)
|
||||
#else
|
||||
/* If defined as something else, make sure we declare it here so it's ready for use */
|
||||
#ifdef UNITY_OUTPUT_CHAR_HEADER_DECLARATION
|
||||
extern void UNITY_OUTPUT_CHAR_HEADER_DECLARATION;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef UNITY_OUTPUT_FLUSH
|
||||
#ifdef UNITY_USE_FLUSH_STDOUT
|
||||
/* We want to use the stdout flush utility */
|
||||
#include <stdio.h>
|
||||
#define UNITY_OUTPUT_FLUSH() (void)fflush(stdout)
|
||||
#else
|
||||
/* We've specified nothing, therefore flush should just be ignored */
|
||||
#define UNITY_OUTPUT_FLUSH()
|
||||
#endif
|
||||
#else
|
||||
/* We've defined flush as something else, so make sure we declare it here so it's ready for use */
|
||||
#ifdef UNITY_OUTPUT_FLUSH_HEADER_DECLARATION
|
||||
extern void UNITY_OMIT_OUTPUT_FLUSH_HEADER_DECLARATION;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef UNITY_OUTPUT_FLUSH
|
||||
#define UNITY_FLUSH_CALL()
|
||||
#else
|
||||
#define UNITY_FLUSH_CALL() UNITY_OUTPUT_FLUSH()
|
||||
#endif
|
||||
|
||||
#ifndef UNITY_PRINT_EOL
|
||||
#define UNITY_PRINT_EOL() UNITY_OUTPUT_CHAR('\n')
|
||||
#endif
|
||||
|
||||
#ifndef UNITY_OUTPUT_START
|
||||
#define UNITY_OUTPUT_START()
|
||||
#endif
|
||||
|
||||
#ifndef UNITY_OUTPUT_COMPLETE
|
||||
#define UNITY_OUTPUT_COMPLETE()
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------
|
||||
* Footprint
|
||||
*-------------------------------------------------------*/
|
||||
|
||||
#ifndef UNITY_LINE_TYPE
|
||||
#define UNITY_LINE_TYPE UNITY_UINT
|
||||
#endif
|
||||
|
||||
#ifndef UNITY_COUNTER_TYPE
|
||||
#define UNITY_COUNTER_TYPE UNITY_UINT
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------
|
||||
* Language Features Available
|
||||
*-------------------------------------------------------*/
|
||||
#if !defined(UNITY_WEAK_ATTRIBUTE) && !defined(UNITY_WEAK_PRAGMA)
|
||||
# if defined(__GNUC__) || defined(__ghs__) /* __GNUC__ includes clang */
|
||||
# if !(defined(__WIN32__) && defined(__clang__)) && !defined(__TMS470__)
|
||||
# define UNITY_WEAK_ATTRIBUTE __attribute__((weak))
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef UNITY_NO_WEAK
|
||||
# undef UNITY_WEAK_ATTRIBUTE
|
||||
# undef UNITY_WEAK_PRAGMA
|
||||
#endif
|
||||
|
||||
|
||||
/*-------------------------------------------------------
|
||||
* Internal Structs Needed
|
||||
*-------------------------------------------------------*/
|
||||
|
||||
typedef void (*UnityTestFunction)(void);
|
||||
|
||||
#define UNITY_DISPLAY_RANGE_INT (0x10)
|
||||
#define UNITY_DISPLAY_RANGE_UINT (0x20)
|
||||
#define UNITY_DISPLAY_RANGE_HEX (0x40)
|
||||
|
||||
typedef enum
|
||||
{
|
||||
UNITY_DISPLAY_STYLE_INT = sizeof(int)+ UNITY_DISPLAY_RANGE_INT,
|
||||
UNITY_DISPLAY_STYLE_INT8 = 1 + UNITY_DISPLAY_RANGE_INT,
|
||||
UNITY_DISPLAY_STYLE_INT16 = 2 + UNITY_DISPLAY_RANGE_INT,
|
||||
UNITY_DISPLAY_STYLE_INT32 = 4 + UNITY_DISPLAY_RANGE_INT,
|
||||
#ifdef UNITY_SUPPORT_64
|
||||
UNITY_DISPLAY_STYLE_INT64 = 8 + UNITY_DISPLAY_RANGE_INT,
|
||||
#endif
|
||||
|
||||
UNITY_DISPLAY_STYLE_UINT = sizeof(unsigned) + UNITY_DISPLAY_RANGE_UINT,
|
||||
UNITY_DISPLAY_STYLE_UINT8 = 1 + UNITY_DISPLAY_RANGE_UINT,
|
||||
UNITY_DISPLAY_STYLE_UINT16 = 2 + UNITY_DISPLAY_RANGE_UINT,
|
||||
UNITY_DISPLAY_STYLE_UINT32 = 4 + UNITY_DISPLAY_RANGE_UINT,
|
||||
#ifdef UNITY_SUPPORT_64
|
||||
UNITY_DISPLAY_STYLE_UINT64 = 8 + UNITY_DISPLAY_RANGE_UINT,
|
||||
#endif
|
||||
|
||||
UNITY_DISPLAY_STYLE_HEX8 = 1 + UNITY_DISPLAY_RANGE_HEX,
|
||||
UNITY_DISPLAY_STYLE_HEX16 = 2 + UNITY_DISPLAY_RANGE_HEX,
|
||||
UNITY_DISPLAY_STYLE_HEX32 = 4 + UNITY_DISPLAY_RANGE_HEX,
|
||||
#ifdef UNITY_SUPPORT_64
|
||||
UNITY_DISPLAY_STYLE_HEX64 = 8 + UNITY_DISPLAY_RANGE_HEX,
|
||||
#endif
|
||||
|
||||
UNITY_DISPLAY_STYLE_UNKNOWN
|
||||
} UNITY_DISPLAY_STYLE_T;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
UNITY_EQUAL_TO = 1,
|
||||
UNITY_GREATER_THAN = 2,
|
||||
UNITY_GREATER_OR_EQUAL = 2 + UNITY_EQUAL_TO,
|
||||
UNITY_SMALLER_THAN = 4,
|
||||
UNITY_SMALLER_OR_EQUAL = 4 + UNITY_EQUAL_TO
|
||||
} UNITY_COMPARISON_T;
|
||||
|
||||
#ifndef UNITY_EXCLUDE_FLOAT
|
||||
typedef enum UNITY_FLOAT_TRAIT
|
||||
{
|
||||
UNITY_FLOAT_IS_NOT_INF = 0,
|
||||
UNITY_FLOAT_IS_INF,
|
||||
UNITY_FLOAT_IS_NOT_NEG_INF,
|
||||
UNITY_FLOAT_IS_NEG_INF,
|
||||
UNITY_FLOAT_IS_NOT_NAN,
|
||||
UNITY_FLOAT_IS_NAN,
|
||||
UNITY_FLOAT_IS_NOT_DET,
|
||||
UNITY_FLOAT_IS_DET,
|
||||
UNITY_FLOAT_INVALID_TRAIT
|
||||
} UNITY_FLOAT_TRAIT_T;
|
||||
#endif
|
||||
|
||||
typedef enum
|
||||
{
|
||||
UNITY_ARRAY_TO_VAL = 0,
|
||||
UNITY_ARRAY_TO_ARRAY
|
||||
} UNITY_FLAGS_T;
|
||||
|
||||
struct UNITY_STORAGE_T
|
||||
{
|
||||
const char* TestFile;
|
||||
const char* CurrentTestName;
|
||||
#ifndef UNITY_EXCLUDE_DETAILS
|
||||
const char* CurrentDetail1;
|
||||
const char* CurrentDetail2;
|
||||
#endif
|
||||
UNITY_LINE_TYPE CurrentTestLineNumber;
|
||||
UNITY_COUNTER_TYPE NumberOfTests;
|
||||
UNITY_COUNTER_TYPE TestFailures;
|
||||
UNITY_COUNTER_TYPE TestIgnores;
|
||||
UNITY_COUNTER_TYPE CurrentTestFailed;
|
||||
UNITY_COUNTER_TYPE CurrentTestIgnored;
|
||||
#ifndef UNITY_EXCLUDE_SETJMP_H
|
||||
jmp_buf AbortFrame;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern struct UNITY_STORAGE_T Unity;
|
||||
|
||||
/*-------------------------------------------------------
|
||||
* Test Suite Management
|
||||
*-------------------------------------------------------*/
|
||||
|
||||
void UnityBegin(const char* filename);
|
||||
int UnityEnd(void);
|
||||
void UnityConcludeTest(void);
|
||||
void UnityDefaultTestRun(UnityTestFunction Func, const char* FuncName, const int FuncLineNum);
|
||||
|
||||
/*-------------------------------------------------------
|
||||
* Details Support
|
||||
*-------------------------------------------------------*/
|
||||
|
||||
#ifdef UNITY_EXCLUDE_DETAILS
|
||||
#define UNITY_CLR_DETAILS()
|
||||
#define UNITY_SET_DETAIL(d1)
|
||||
#define UNITY_SET_DETAILS(d1,d2)
|
||||
#else
|
||||
#define UNITY_CLR_DETAILS() { Unity.CurrentDetail1 = 0; Unity.CurrentDetail2 = 0; }
|
||||
#define UNITY_SET_DETAIL(d1) { Unity.CurrentDetail1 = d1; Unity.CurrentDetail2 = 0; }
|
||||
#define UNITY_SET_DETAILS(d1,d2) { Unity.CurrentDetail1 = d1; Unity.CurrentDetail2 = d2; }
|
||||
|
||||
#ifndef UNITY_DETAIL1_NAME
|
||||
#define UNITY_DETAIL1_NAME "Function"
|
||||
#endif
|
||||
|
||||
#ifndef UNITY_DETAIL2_NAME
|
||||
#define UNITY_DETAIL2_NAME "Argument"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------
|
||||
* Test Output
|
||||
*-------------------------------------------------------*/
|
||||
|
||||
void UnityPrint(const char* string);
|
||||
void UnityPrintLen(const char* string, const UNITY_UINT32 length);
|
||||
void UnityPrintMask(const UNITY_UINT mask, const UNITY_UINT number);
|
||||
void UnityPrintNumberByStyle(const UNITY_INT number, const UNITY_DISPLAY_STYLE_T style);
|
||||
void UnityPrintNumber(const UNITY_INT number);
|
||||
void UnityPrintNumberUnsigned(const UNITY_UINT number);
|
||||
void UnityPrintNumberHex(const UNITY_UINT number, const char nibbles);
|
||||
|
||||
#ifndef UNITY_EXCLUDE_FLOAT_PRINT
|
||||
void UnityPrintFloat(const UNITY_DOUBLE input_number);
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------
|
||||
* Test Assertion Functions
|
||||
*-------------------------------------------------------
|
||||
* Use the macros below this section instead of calling
|
||||
* these directly. The macros have a consistent naming
|
||||
* convention and will pull in file and line information
|
||||
* for you. */
|
||||
|
||||
void UnityAssertEqualNumber(const UNITY_INT expected,
|
||||
const UNITY_INT actual,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber,
|
||||
const UNITY_DISPLAY_STYLE_T style);
|
||||
|
||||
void UnityAssertGreaterOrLessOrEqualNumber(const UNITY_INT threshold,
|
||||
const UNITY_INT actual,
|
||||
const UNITY_COMPARISON_T compare,
|
||||
const char *msg,
|
||||
const UNITY_LINE_TYPE lineNumber,
|
||||
const UNITY_DISPLAY_STYLE_T style);
|
||||
|
||||
void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected,
|
||||
UNITY_INTERNAL_PTR actual,
|
||||
const UNITY_UINT32 num_elements,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber,
|
||||
const UNITY_DISPLAY_STYLE_T style,
|
||||
const UNITY_FLAGS_T flags);
|
||||
|
||||
void UnityAssertBits(const UNITY_INT mask,
|
||||
const UNITY_INT expected,
|
||||
const UNITY_INT actual,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber);
|
||||
|
||||
void UnityAssertEqualString(const char* expected,
|
||||
const char* actual,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber);
|
||||
|
||||
void UnityAssertEqualStringLen(const char* expected,
|
||||
const char* actual,
|
||||
const UNITY_UINT32 length,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber);
|
||||
|
||||
void UnityAssertEqualStringArray( UNITY_INTERNAL_PTR expected,
|
||||
const char** actual,
|
||||
const UNITY_UINT32 num_elements,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber,
|
||||
const UNITY_FLAGS_T flags);
|
||||
|
||||
void UnityAssertEqualMemory( UNITY_INTERNAL_PTR expected,
|
||||
UNITY_INTERNAL_PTR actual,
|
||||
const UNITY_UINT32 length,
|
||||
const UNITY_UINT32 num_elements,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber,
|
||||
const UNITY_FLAGS_T flags);
|
||||
|
||||
void UnityAssertNumbersWithin(const UNITY_UINT delta,
|
||||
const UNITY_INT expected,
|
||||
const UNITY_INT actual,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber,
|
||||
const UNITY_DISPLAY_STYLE_T style);
|
||||
|
||||
void UnityFail(const char* message, const UNITY_LINE_TYPE line);
|
||||
|
||||
void UnityIgnore(const char* message, const UNITY_LINE_TYPE line);
|
||||
|
||||
#ifndef UNITY_EXCLUDE_FLOAT
|
||||
void UnityAssertFloatsWithin(const UNITY_FLOAT delta,
|
||||
const UNITY_FLOAT expected,
|
||||
const UNITY_FLOAT actual,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber);
|
||||
|
||||
void UnityAssertEqualFloatArray(UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* expected,
|
||||
UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* actual,
|
||||
const UNITY_UINT32 num_elements,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber,
|
||||
const UNITY_FLAGS_T flags);
|
||||
|
||||
void UnityAssertFloatSpecial(const UNITY_FLOAT actual,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber,
|
||||
const UNITY_FLOAT_TRAIT_T style);
|
||||
#endif
|
||||
|
||||
#ifndef UNITY_EXCLUDE_DOUBLE
|
||||
void UnityAssertDoublesWithin(const UNITY_DOUBLE delta,
|
||||
const UNITY_DOUBLE expected,
|
||||
const UNITY_DOUBLE actual,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber);
|
||||
|
||||
void UnityAssertEqualDoubleArray(UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* expected,
|
||||
UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* actual,
|
||||
const UNITY_UINT32 num_elements,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber,
|
||||
const UNITY_FLAGS_T flags);
|
||||
|
||||
void UnityAssertDoubleSpecial(const UNITY_DOUBLE actual,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber,
|
||||
const UNITY_FLOAT_TRAIT_T style);
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------
|
||||
* Helpers
|
||||
*-------------------------------------------------------*/
|
||||
|
||||
UNITY_INTERNAL_PTR UnityNumToPtr(const UNITY_INT num, const UNITY_UINT8 size);
|
||||
#ifndef UNITY_EXCLUDE_FLOAT
|
||||
UNITY_INTERNAL_PTR UnityFloatToPtr(const float num);
|
||||
#endif
|
||||
#ifndef UNITY_EXCLUDE_DOUBLE
|
||||
UNITY_INTERNAL_PTR UnityDoubleToPtr(const double num);
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------
|
||||
* Error Strings We Might Need
|
||||
*-------------------------------------------------------*/
|
||||
|
||||
extern const char UnityStrErrFloat[];
|
||||
extern const char UnityStrErrDouble[];
|
||||
extern const char UnityStrErr64[];
|
||||
|
||||
/*-------------------------------------------------------
|
||||
* Test Running Macros
|
||||
*-------------------------------------------------------*/
|
||||
|
||||
#ifndef UNITY_EXCLUDE_SETJMP_H
|
||||
#define TEST_PROTECT() (setjmp(Unity.AbortFrame) == 0)
|
||||
#define TEST_ABORT() longjmp(Unity.AbortFrame, 1)
|
||||
#else
|
||||
#define TEST_PROTECT() 1
|
||||
#define TEST_ABORT() return
|
||||
#endif
|
||||
|
||||
/* This tricky series of macros gives us an optional line argument to treat it as RUN_TEST(func, num=__LINE__) */
|
||||
#ifndef RUN_TEST
|
||||
#ifdef __STDC_VERSION__
|
||||
#if __STDC_VERSION__ >= 199901L
|
||||
#define RUN_TEST(...) UnityDefaultTestRun(RUN_TEST_FIRST(__VA_ARGS__), RUN_TEST_SECOND(__VA_ARGS__))
|
||||
#define RUN_TEST_FIRST(...) RUN_TEST_FIRST_HELPER(__VA_ARGS__, throwaway)
|
||||
#define RUN_TEST_FIRST_HELPER(first, ...) (first), #first
|
||||
#define RUN_TEST_SECOND(...) RUN_TEST_SECOND_HELPER(__VA_ARGS__, __LINE__, throwaway)
|
||||
#define RUN_TEST_SECOND_HELPER(first, second, ...) (second)
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* If we can't do the tricky version, we'll just have to require them to always include the line number */
|
||||
#ifndef RUN_TEST
|
||||
#ifdef CMOCK
|
||||
#define RUN_TEST(func, num) UnityDefaultTestRun(func, #func, num)
|
||||
#else
|
||||
#define RUN_TEST(func) UnityDefaultTestRun(func, #func, __LINE__)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define TEST_LINE_NUM (Unity.CurrentTestLineNumber)
|
||||
#define TEST_IS_IGNORED (Unity.CurrentTestIgnored)
|
||||
#define UNITY_NEW_TEST(a) \
|
||||
Unity.CurrentTestName = (a); \
|
||||
Unity.CurrentTestLineNumber = (UNITY_LINE_TYPE)(__LINE__); \
|
||||
Unity.NumberOfTests++;
|
||||
|
||||
#ifndef UNITY_BEGIN
|
||||
#define UNITY_BEGIN() UnityBegin(__FILE__)
|
||||
#endif
|
||||
|
||||
#ifndef UNITY_END
|
||||
#define UNITY_END() UnityEnd()
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------
|
||||
* Command Line Argument Support
|
||||
*-----------------------------------------------*/
|
||||
|
||||
#ifdef UNITY_USE_COMMAND_LINE_ARGS
|
||||
int UnityParseOptions(int argc, char** argv);
|
||||
int UnityTestMatches(void);
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------
|
||||
* Basic Fail and Ignore
|
||||
*-------------------------------------------------------*/
|
||||
|
||||
#define UNITY_TEST_FAIL(line, message) UnityFail( (message), (UNITY_LINE_TYPE)(line))
|
||||
#define UNITY_TEST_IGNORE(line, message) UnityIgnore( (message), (UNITY_LINE_TYPE)(line))
|
||||
|
||||
/*-------------------------------------------------------
|
||||
* Test Asserts
|
||||
*-------------------------------------------------------*/
|
||||
|
||||
#define UNITY_TEST_ASSERT(condition, line, message) if (condition) {} else {UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), (message));}
|
||||
#define UNITY_TEST_ASSERT_NULL(pointer, line, message) UNITY_TEST_ASSERT(((pointer) == NULL), (UNITY_LINE_TYPE)(line), (message))
|
||||
#define UNITY_TEST_ASSERT_NOT_NULL(pointer, line, message) UNITY_TEST_ASSERT(((pointer) != NULL), (UNITY_LINE_TYPE)(line), (message))
|
||||
|
||||
#define UNITY_TEST_ASSERT_EQUAL_INT(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_INT8(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT8 )(expected), (UNITY_INT)(UNITY_INT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_INT16(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT16)(expected), (UNITY_INT)(UNITY_INT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_INT32(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT32)(expected), (UNITY_INT)(UNITY_INT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_UINT(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_UINT8(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_UINT8 )(expected), (UNITY_INT)(UNITY_UINT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_UINT16(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_UINT16)(expected), (UNITY_INT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_UINT32(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_UINT32)(expected), (UNITY_INT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_HEX8(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT8 )(expected), (UNITY_INT)(UNITY_INT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_HEX16(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT16)(expected), (UNITY_INT)(UNITY_INT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_HEX32(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT32)(expected), (UNITY_INT)(UNITY_INT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32)
|
||||
#define UNITY_TEST_ASSERT_BITS(mask, expected, actual, line, message) UnityAssertBits((UNITY_INT)(mask), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line))
|
||||
|
||||
#define UNITY_TEST_ASSERT_GREATER_THAN_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT)
|
||||
#define UNITY_TEST_ASSERT_GREATER_THAN_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8)
|
||||
#define UNITY_TEST_ASSERT_GREATER_THAN_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16)
|
||||
#define UNITY_TEST_ASSERT_GREATER_THAN_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32)
|
||||
#define UNITY_TEST_ASSERT_GREATER_THAN_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT)
|
||||
#define UNITY_TEST_ASSERT_GREATER_THAN_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8)
|
||||
#define UNITY_TEST_ASSERT_GREATER_THAN_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16)
|
||||
#define UNITY_TEST_ASSERT_GREATER_THAN_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32)
|
||||
#define UNITY_TEST_ASSERT_GREATER_THAN_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8)
|
||||
#define UNITY_TEST_ASSERT_GREATER_THAN_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16)
|
||||
#define UNITY_TEST_ASSERT_GREATER_THAN_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32)
|
||||
|
||||
#define UNITY_TEST_ASSERT_SMALLER_THAN_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT)
|
||||
#define UNITY_TEST_ASSERT_SMALLER_THAN_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8)
|
||||
#define UNITY_TEST_ASSERT_SMALLER_THAN_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16)
|
||||
#define UNITY_TEST_ASSERT_SMALLER_THAN_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32)
|
||||
#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT)
|
||||
#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8)
|
||||
#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16)
|
||||
#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32)
|
||||
#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8)
|
||||
#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16)
|
||||
#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32)
|
||||
|
||||
#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT)
|
||||
#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8)
|
||||
#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16)
|
||||
#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32)
|
||||
#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT)
|
||||
#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8)
|
||||
#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16)
|
||||
#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32)
|
||||
#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8)
|
||||
#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16)
|
||||
#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32)
|
||||
|
||||
#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT)
|
||||
#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8)
|
||||
#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16)
|
||||
#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32)
|
||||
#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT)
|
||||
#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8)
|
||||
#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16)
|
||||
#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32)
|
||||
#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8)
|
||||
#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16)
|
||||
#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32)
|
||||
|
||||
#define UNITY_TEST_ASSERT_INT_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT)
|
||||
#define UNITY_TEST_ASSERT_INT8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_INT8 )(expected), (UNITY_INT)(UNITY_INT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8)
|
||||
#define UNITY_TEST_ASSERT_INT16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT16)(delta), (UNITY_INT)(UNITY_INT16)(expected), (UNITY_INT)(UNITY_INT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16)
|
||||
#define UNITY_TEST_ASSERT_INT32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT32)(delta), (UNITY_INT)(UNITY_INT32)(expected), (UNITY_INT)(UNITY_INT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32)
|
||||
#define UNITY_TEST_ASSERT_UINT_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT)
|
||||
#define UNITY_TEST_ASSERT_UINT8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8)
|
||||
#define UNITY_TEST_ASSERT_UINT16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT16)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16)
|
||||
#define UNITY_TEST_ASSERT_UINT32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT32)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32)
|
||||
#define UNITY_TEST_ASSERT_HEX8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8)
|
||||
#define UNITY_TEST_ASSERT_HEX16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT16)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16)
|
||||
#define UNITY_TEST_ASSERT_HEX32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT32)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32)
|
||||
|
||||
#define UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, line, message) UnityAssertEqualNumber((UNITY_PTR_TO_INT)(expected), (UNITY_PTR_TO_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_STRING(expected, actual, line, message) UnityAssertEqualString((const char*)(expected), (const char*)(actual), (message), (UNITY_LINE_TYPE)(line))
|
||||
#define UNITY_TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len, line, message) UnityAssertEqualStringLen((const char*)(expected), (const char*)(actual), (UNITY_UINT32)(len), (message), (UNITY_LINE_TYPE)(line))
|
||||
#define UNITY_TEST_ASSERT_EQUAL_MEMORY(expected, actual, len, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), 1, (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY)
|
||||
|
||||
#define UNITY_TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT, UNITY_ARRAY_TO_ARRAY)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8, UNITY_ARRAY_TO_ARRAY)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16, UNITY_ARRAY_TO_ARRAY)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32, UNITY_ARRAY_TO_ARRAY)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT, UNITY_ARRAY_TO_ARRAY)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_ARRAY)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16, UNITY_ARRAY_TO_ARRAY)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32, UNITY_ARRAY_TO_ARRAY)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8, UNITY_ARRAY_TO_ARRAY)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16, UNITY_ARRAY_TO_ARRAY)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32, UNITY_ARRAY_TO_ARRAY)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER, UNITY_ARRAY_TO_ARRAY)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualStringArray((UNITY_INTERNAL_PTR)(expected), (const char**)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected, actual, len, num_elements, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY)
|
||||
|
||||
#define UNITY_TEST_ASSERT_EACH_EQUAL_INT(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT) expected, sizeof(int)), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT, UNITY_ARRAY_TO_VAL)
|
||||
#define UNITY_TEST_ASSERT_EACH_EQUAL_INT8(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT8 )expected, 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8, UNITY_ARRAY_TO_VAL)
|
||||
#define UNITY_TEST_ASSERT_EACH_EQUAL_INT16(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT16 )expected, 2), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16, UNITY_ARRAY_TO_VAL)
|
||||
#define UNITY_TEST_ASSERT_EACH_EQUAL_INT32(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT32 )expected, 4), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32, UNITY_ARRAY_TO_VAL)
|
||||
#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT) expected, sizeof(unsigned int)), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT, UNITY_ARRAY_TO_VAL)
|
||||
#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT8(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT8 )expected, 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_VAL)
|
||||
#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT16(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT16)expected, 2), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16, UNITY_ARRAY_TO_VAL)
|
||||
#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT32(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT32)expected, 4), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32, UNITY_ARRAY_TO_VAL)
|
||||
#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX8(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT8 )expected, 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8, UNITY_ARRAY_TO_VAL)
|
||||
#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX16(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT16 )expected, 2), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16, UNITY_ARRAY_TO_VAL)
|
||||
#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX32(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT32 )expected, 4), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32, UNITY_ARRAY_TO_VAL)
|
||||
#define UNITY_TEST_ASSERT_EACH_EQUAL_PTR(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_PTR_TO_INT) expected, sizeof(int*)), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER, UNITY_ARRAY_TO_VAL)
|
||||
#define UNITY_TEST_ASSERT_EACH_EQUAL_STRING(expected, actual, num_elements, line, message) UnityAssertEqualStringArray((UNITY_INTERNAL_PTR)(expected), (const char**)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL)
|
||||
#define UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY(expected, actual, len, num_elements, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL)
|
||||
|
||||
#ifdef UNITY_SUPPORT_64
|
||||
#define UNITY_TEST_ASSERT_EQUAL_INT64(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_UINT64(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_HEX64(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64, UNITY_ARRAY_TO_ARRAY)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_ARRAY)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64, UNITY_ARRAY_TO_ARRAY)
|
||||
#define UNITY_TEST_ASSERT_EACH_EQUAL_INT64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT64)expected, 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64, UNITY_ARRAY_TO_VAL)
|
||||
#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT64)expected, 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_VAL)
|
||||
#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT64)expected, 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64, UNITY_ARRAY_TO_VAL)
|
||||
#define UNITY_TEST_ASSERT_INT64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64)
|
||||
#define UNITY_TEST_ASSERT_UINT64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64)
|
||||
#define UNITY_TEST_ASSERT_HEX64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64)
|
||||
#define UNITY_TEST_ASSERT_GREATER_THAN_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64)
|
||||
#define UNITY_TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64)
|
||||
#define UNITY_TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64)
|
||||
#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64)
|
||||
#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64)
|
||||
#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64)
|
||||
#define UNITY_TEST_ASSERT_SMALLER_THAN_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64)
|
||||
#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64)
|
||||
#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64)
|
||||
#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64)
|
||||
#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64)
|
||||
#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64)
|
||||
#else
|
||||
#define UNITY_TEST_ASSERT_EQUAL_INT64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_UINT64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_HEX64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
|
||||
#define UNITY_TEST_ASSERT_INT64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
|
||||
#define UNITY_TEST_ASSERT_UINT64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
|
||||
#define UNITY_TEST_ASSERT_HEX64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
|
||||
#define UNITY_TEST_ASSERT_GREATER_THAN_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
|
||||
#define UNITY_TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
|
||||
#define UNITY_TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
|
||||
#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
|
||||
#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
|
||||
#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
|
||||
#define UNITY_TEST_ASSERT_SMALLER_THAN_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
|
||||
#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
|
||||
#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
|
||||
#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
|
||||
#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
|
||||
#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
|
||||
#endif
|
||||
|
||||
#ifdef UNITY_EXCLUDE_FLOAT
|
||||
#define UNITY_TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
|
||||
#define UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
|
||||
#define UNITY_TEST_ASSERT_FLOAT_IS_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
|
||||
#define UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
|
||||
#define UNITY_TEST_ASSERT_FLOAT_IS_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
|
||||
#define UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
|
||||
#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
|
||||
#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
|
||||
#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
|
||||
#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
|
||||
#else
|
||||
#define UNITY_TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual, line, message) UnityAssertFloatsWithin((UNITY_FLOAT)(delta), (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line))
|
||||
#define UNITY_TEST_ASSERT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_ASSERT_FLOAT_WITHIN((UNITY_FLOAT)(expected) * (UNITY_FLOAT)UNITY_FLOAT_PRECISION, (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (UNITY_LINE_TYPE)(line), (message))
|
||||
#define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualFloatArray((UNITY_FLOAT*)(expected), (UNITY_FLOAT*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY)
|
||||
#define UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements, line, message) UnityAssertEqualFloatArray(UnityFloatToPtr(expected), (UNITY_FLOAT*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL)
|
||||
#define UNITY_TEST_ASSERT_FLOAT_IS_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_INF)
|
||||
#define UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NEG_INF)
|
||||
#define UNITY_TEST_ASSERT_FLOAT_IS_NAN(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NAN)
|
||||
#define UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_DET)
|
||||
#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_INF)
|
||||
#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NEG_INF)
|
||||
#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NAN)
|
||||
#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_DET)
|
||||
#endif
|
||||
|
||||
#ifdef UNITY_EXCLUDE_DOUBLE
|
||||
#define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
|
||||
#define UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
|
||||
#define UNITY_TEST_ASSERT_DOUBLE_IS_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
|
||||
#define UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
|
||||
#define UNITY_TEST_ASSERT_DOUBLE_IS_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
|
||||
#define UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
|
||||
#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
|
||||
#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
|
||||
#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
|
||||
#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
|
||||
#else
|
||||
#define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message) UnityAssertDoublesWithin((UNITY_DOUBLE)(delta), (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)line)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_ASSERT_DOUBLE_WITHIN((UNITY_DOUBLE)(expected) * (UNITY_DOUBLE)UNITY_DOUBLE_PRECISION, (UNITY_DOUBLE)expected, (UNITY_DOUBLE)actual, (UNITY_LINE_TYPE)(line), message)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualDoubleArray((UNITY_DOUBLE*)(expected), (UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)line, UNITY_ARRAY_TO_ARRAY)
|
||||
#define UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements, line, message) UnityAssertEqualDoubleArray(UnityDoubleToPtr(expected), (UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)line, UNITY_ARRAY_TO_VAL)
|
||||
#define UNITY_TEST_ASSERT_DOUBLE_IS_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_INF)
|
||||
#define UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NEG_INF)
|
||||
#define UNITY_TEST_ASSERT_DOUBLE_IS_NAN(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NAN)
|
||||
#define UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_DET)
|
||||
#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_INF)
|
||||
#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NEG_INF)
|
||||
#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NAN)
|
||||
#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_DET)
|
||||
#endif
|
||||
|
||||
/* End of UNITY_INTERNALS_H */
|
||||
#endif
|
||||
1
3rd/libzmq/external/unity/version.txt
vendored
Normal file
1
3rd/libzmq/external/unity/version.txt
vendored
Normal file
@@ -0,0 +1 @@
|
||||
https://github.com/ThrowTheSwitch/Unity/commit/b4aca70fd9e0ddf0afbdafb1b826f5edcfc1049b
|
||||
202
3rd/libzmq/external/wepoll/README.md
vendored
Normal file
202
3rd/libzmq/external/wepoll/README.md
vendored
Normal file
@@ -0,0 +1,202 @@
|
||||
# wepoll - epoll for windows
|
||||
|
||||
[![][ci status badge]][ci status link]
|
||||
|
||||
This library implements the [epoll][man epoll] API for Windows
|
||||
applications. It is fast and scalable, and it closely resembles the API
|
||||
and behavior of Linux' epoll.
|
||||
|
||||
## Rationale
|
||||
|
||||
Unlike Linux, OS X, and many other operating systems, Windows doesn't
|
||||
have a good API for receiving socket state notifications. It only
|
||||
supports the `select` and `WSAPoll` APIs, but they
|
||||
[don't scale][select scale] and suffer from
|
||||
[other issues][wsapoll broken].
|
||||
|
||||
Using I/O completion ports isn't always practical when software is
|
||||
designed to be cross-platform. Wepoll offers an alternative that is
|
||||
much closer to a drop-in replacement for software that was designed
|
||||
to run on Linux.
|
||||
|
||||
## Features
|
||||
|
||||
* Can poll 100000s of sockets efficiently.
|
||||
* Fully thread-safe.
|
||||
* Multiple threads can poll the same epoll port.
|
||||
* Sockets can be added to multiple epoll sets.
|
||||
* All epoll events (`EPOLLIN`, `EPOLLOUT`, `EPOLLPRI`, `EPOLLRDHUP`)
|
||||
are supported.
|
||||
* Level-triggered and one-shot (`EPOLLONESTHOT`) modes are supported
|
||||
* Trivial to embed: you need [only two files][dist].
|
||||
|
||||
## Limitations
|
||||
|
||||
* Only works with sockets.
|
||||
* Edge-triggered (`EPOLLET`) mode isn't supported.
|
||||
|
||||
## How to use
|
||||
|
||||
The library is [distributed][dist] as a single source file
|
||||
([wepoll.c][wepoll.c]) and a single header file ([wepoll.h][wepoll.h]).<br>
|
||||
Compile the .c file as part of your project, and include the header wherever
|
||||
needed.
|
||||
|
||||
## Compatibility
|
||||
|
||||
* Requires Windows Vista or higher.
|
||||
* Can be compiled with recent versions of MSVC, Clang, and GCC.
|
||||
|
||||
## API
|
||||
|
||||
### General remarks
|
||||
|
||||
* The epoll port is a `HANDLE`, not a file descriptor.
|
||||
* All functions set both `errno` and `GetLastError()` on failure.
|
||||
* For more extensive documentation, see the [epoll(7) man page][man epoll],
|
||||
and the per-function man pages that are linked below.
|
||||
|
||||
### epoll_create/epoll_create1
|
||||
|
||||
```c
|
||||
HANDLE epoll_create(int size);
|
||||
HANDLE epoll_create1(int flags);
|
||||
```
|
||||
|
||||
* Create a new epoll instance (port).
|
||||
* `size` is ignored but most be greater than zero.
|
||||
* `flags` must be zero as there are no supported flags.
|
||||
* Returns `NULL` on failure.
|
||||
* [Linux man page][man epoll_create]
|
||||
|
||||
### epoll_close
|
||||
|
||||
```c
|
||||
int epoll_close(HANDLE ephnd);
|
||||
```
|
||||
|
||||
* Close an epoll port.
|
||||
* Do not attempt to close the epoll port with `close()`,
|
||||
`CloseHandle()` or `closesocket()`.
|
||||
|
||||
### epoll_ctl
|
||||
|
||||
```c
|
||||
int epoll_ctl(HANDLE ephnd,
|
||||
int op,
|
||||
SOCKET sock,
|
||||
struct epoll_event* event);
|
||||
```
|
||||
|
||||
* Control which socket events are monitored by an epoll port.
|
||||
* `ephnd` must be a HANDLE created by
|
||||
[`epoll_create()`](#epoll_createepoll_create1) or
|
||||
[`epoll_create1()`](#epoll_createepoll_create1).
|
||||
* `op` must be one of `EPOLL_CTL_ADD`, `EPOLL_CTL_MOD`, `EPOLL_CTL_DEL`.
|
||||
* `sock` must be a valid socket created by [`socket()`][msdn socket],
|
||||
[`WSASocket()`][msdn wsasocket], or [`accept()`][msdn accept].
|
||||
* `event` should be a pointer to a [`struct epoll_event`](#struct-epoll_event).<br>
|
||||
If `op` is `EPOLL_CTL_DEL` then the `event` parameter is ignored, and it
|
||||
may be `NULL`.
|
||||
* Returns 0 on success, -1 on failure.
|
||||
* It is recommended to always explicitly remove a socket from its epoll
|
||||
set using `EPOLL_CTL_DEL` *before* closing it.<br>
|
||||
As on Linux, closed sockets are automatically removed from the epoll set, but
|
||||
wepoll may not be able to detect that a socket was closed until the next call
|
||||
to [`epoll_wait()`](#epoll_wait).
|
||||
* [Linux man page][man epoll_ctl]
|
||||
|
||||
### epoll_wait
|
||||
|
||||
```c
|
||||
int epoll_wait(HANDLE ephnd,
|
||||
struct epoll_event* events,
|
||||
int maxevents,
|
||||
int timeout);
|
||||
```
|
||||
|
||||
* Receive socket events from an epoll port.
|
||||
* `events` should point to a caller-allocated array of
|
||||
[`epoll_event`](#struct-epoll_event) structs, which will receive the
|
||||
reported events.
|
||||
* `maxevents` is the maximum number of events that will be written to the
|
||||
`events` array, and must be greater than zero.
|
||||
* `timeout` specifies whether to block when no events are immediately available.
|
||||
- `<0` block indefinitely
|
||||
- `0` report any events that are already waiting, but don't block
|
||||
- `≥1` block for at most N milliseconds
|
||||
* Return value:
|
||||
- `-1` an error occurred
|
||||
- `0` timed out without any events to report
|
||||
- `≥1` the number of events stored in the `events` buffer
|
||||
* [Linux man page][man epoll_wait]
|
||||
|
||||
### struct epoll_event
|
||||
|
||||
```c
|
||||
typedef union epoll_data {
|
||||
void* ptr;
|
||||
int fd;
|
||||
uint32_t u32;
|
||||
uint64_t u64;
|
||||
SOCKET sock; /* Windows specific */
|
||||
HANDLE hnd; /* Windows specific */
|
||||
} epoll_data_t;
|
||||
```
|
||||
|
||||
```c
|
||||
struct epoll_event {
|
||||
uint32_t events; /* Epoll events and flags */
|
||||
epoll_data_t data; /* User data variable */
|
||||
};
|
||||
```
|
||||
|
||||
* The `events` field is a bit mask containing the events being
|
||||
monitored/reported, and optional flags.<br>
|
||||
Flags are accepted by [`epoll_ctl()`](#epoll_ctl), but they are not reported
|
||||
back by [`epoll_wait()`](#epoll_wait).
|
||||
* The `data` field can be used to associate application-specific information
|
||||
with a socket; its value will be returned unmodified by
|
||||
[`epoll_wait()`](#epoll_wait).
|
||||
* [Linux man page][man epoll_ctl]
|
||||
|
||||
| Event | Description |
|
||||
|---------------|----------------------------------------------------------------------|
|
||||
| `EPOLLIN` | incoming data available, or incoming connection ready to be accepted |
|
||||
| `EPOLLOUT` | ready to send data, or outgoing connection successfully established |
|
||||
| `EPOLLRDHUP` | remote peer initiated graceful socket shutdown |
|
||||
| `EPOLLPRI` | out-of-band data available for reading |
|
||||
| `EPOLLERR` | socket error<sup>1</sup> |
|
||||
| `EPOLLHUP` | socket hang-up<sup>1</sup> |
|
||||
| `EPOLLRDNORM` | same as `EPOLLIN` |
|
||||
| `EPOLLRDBAND` | same as `EPOLLPRI` |
|
||||
| `EPOLLWRNORM` | same as `EPOLLOUT` |
|
||||
| `EPOLLWRBAND` | same as `EPOLLOUT` |
|
||||
| `EPOLLMSG` | never reported |
|
||||
|
||||
| Flag | Description |
|
||||
|------------------|---------------------------|
|
||||
| `EPOLLONESHOT` | report event(s) only once |
|
||||
| `EPOLLET` | not supported by wepoll |
|
||||
| `EPOLLEXCLUSIVE` | not supported by wepoll |
|
||||
| `EPOLLWAKEUP` | not supported by wepoll |
|
||||
|
||||
<sup>1</sup>: the `EPOLLERR` and `EPOLLHUP` events may always be reported by
|
||||
[`epoll_wait()`](#epoll_wait), regardless of the event mask that was passed to
|
||||
[`epoll_ctl()`](#epoll_ctl).
|
||||
|
||||
|
||||
[ci status badge]: https://ci.appveyor.com/api/projects/status/github/piscisaureus/wepoll?branch=master&svg=true
|
||||
[ci status link]: https://ci.appveyor.com/project/piscisaureus/wepoll/branch/master
|
||||
[dist]: https://github.com/piscisaureus/wepoll/tree/dist
|
||||
[man epoll]: http://man7.org/linux/man-pages/man7/epoll.7.html
|
||||
[man epoll_create]: http://man7.org/linux/man-pages/man2/epoll_create.2.html
|
||||
[man epoll_ctl]: http://man7.org/linux/man-pages/man2/epoll_ctl.2.html
|
||||
[man epoll_wait]: http://man7.org/linux/man-pages/man2/epoll_wait.2.html
|
||||
[msdn accept]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms737526(v=vs.85).aspx
|
||||
[msdn socket]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms740506(v=vs.85).aspx
|
||||
[msdn wsasocket]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms742212(v=vs.85).aspx
|
||||
[select scale]: https://daniel.haxx.se/docs/poll-vs-select.html
|
||||
[wsapoll broken]: https://daniel.haxx.se/blog/2012/10/10/wsapoll-is-broken/
|
||||
[wepoll.c]: https://github.com/piscisaureus/wepoll/blob/dist/wepoll.c
|
||||
[wepoll.h]: https://github.com/piscisaureus/wepoll/blob/dist/wepoll.h
|
||||
28
3rd/libzmq/external/wepoll/license.txt
vendored
Normal file
28
3rd/libzmq/external/wepoll/license.txt
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
wepoll - epoll for Windows
|
||||
https://github.com/piscisaureus/wepoll
|
||||
|
||||
Copyright 2012-2018, Bert Belder <bertbelder@gmail.com>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
1
3rd/libzmq/external/wepoll/version.txt
vendored
Normal file
1
3rd/libzmq/external/wepoll/version.txt
vendored
Normal file
@@ -0,0 +1 @@
|
||||
https://github.com/piscisaureus/wepoll/tree/v1.5.4
|
||||
2186
3rd/libzmq/external/wepoll/wepoll.c
vendored
Normal file
2186
3rd/libzmq/external/wepoll/wepoll.c
vendored
Normal file
@@ -0,0 +1,2186 @@
|
||||
/*
|
||||
* wepoll - epoll for Windows
|
||||
* https://github.com/piscisaureus/wepoll
|
||||
*
|
||||
* Copyright 2012-2018, Bert Belder <bertbelder@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef WEPOLL_EXPORT
|
||||
#define WEPOLL_EXPORT
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
enum EPOLL_EVENTS {
|
||||
EPOLLIN = (int) (1U << 0),
|
||||
EPOLLPRI = (int) (1U << 1),
|
||||
EPOLLOUT = (int) (1U << 2),
|
||||
EPOLLERR = (int) (1U << 3),
|
||||
EPOLLHUP = (int) (1U << 4),
|
||||
EPOLLRDNORM = (int) (1U << 6),
|
||||
EPOLLRDBAND = (int) (1U << 7),
|
||||
EPOLLWRNORM = (int) (1U << 8),
|
||||
EPOLLWRBAND = (int) (1U << 9),
|
||||
EPOLLMSG = (int) (1U << 10), /* Never reported. */
|
||||
EPOLLRDHUP = (int) (1U << 13),
|
||||
EPOLLONESHOT = (int) (1U << 31)
|
||||
};
|
||||
|
||||
#define EPOLLIN (1U << 0)
|
||||
#define EPOLLPRI (1U << 1)
|
||||
#define EPOLLOUT (1U << 2)
|
||||
#define EPOLLERR (1U << 3)
|
||||
#define EPOLLHUP (1U << 4)
|
||||
#define EPOLLRDNORM (1U << 6)
|
||||
#define EPOLLRDBAND (1U << 7)
|
||||
#define EPOLLWRNORM (1U << 8)
|
||||
#define EPOLLWRBAND (1U << 9)
|
||||
#define EPOLLMSG (1U << 10)
|
||||
#define EPOLLRDHUP (1U << 13)
|
||||
#define EPOLLONESHOT (1U << 31)
|
||||
|
||||
#define EPOLL_CTL_ADD 1
|
||||
#define EPOLL_CTL_MOD 2
|
||||
#define EPOLL_CTL_DEL 3
|
||||
|
||||
/* clang-format on */
|
||||
|
||||
typedef void* HANDLE;
|
||||
typedef uintptr_t SOCKET;
|
||||
|
||||
typedef union epoll_data {
|
||||
void* ptr;
|
||||
int fd;
|
||||
uint32_t u32;
|
||||
uint64_t u64;
|
||||
SOCKET sock; /* Windows specific */
|
||||
HANDLE hnd; /* Windows specific */
|
||||
} epoll_data_t;
|
||||
|
||||
struct epoll_event {
|
||||
uint32_t events; /* Epoll events and flags */
|
||||
epoll_data_t data; /* User data variable */
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
WEPOLL_EXPORT HANDLE epoll_create(int size);
|
||||
WEPOLL_EXPORT HANDLE epoll_create1(int flags);
|
||||
|
||||
WEPOLL_EXPORT int epoll_close(HANDLE ephnd);
|
||||
|
||||
WEPOLL_EXPORT int epoll_ctl(HANDLE ephnd,
|
||||
int op,
|
||||
SOCKET sock,
|
||||
struct epoll_event* event);
|
||||
|
||||
WEPOLL_EXPORT int epoll_wait(HANDLE ephnd,
|
||||
struct epoll_event* events,
|
||||
int maxevents,
|
||||
int timeout);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#include <malloc.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define WEPOLL_INTERNAL static
|
||||
#define WEPOLL_INTERNAL_VAR static
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wreserved-id-macro"
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32_WINNT
|
||||
#undef _WIN32_WINNT
|
||||
#endif
|
||||
|
||||
#define _WIN32_WINNT 0x0600
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#ifndef __GNUC__
|
||||
#pragma warning(push, 1)
|
||||
#endif
|
||||
|
||||
#include <WS2tcpip.h>
|
||||
#include <WinSock2.h>
|
||||
#include <Windows.h>
|
||||
|
||||
#ifndef __GNUC__
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
WEPOLL_INTERNAL int nt_global_init(void);
|
||||
|
||||
typedef LONG NTSTATUS;
|
||||
typedef NTSTATUS* PNTSTATUS;
|
||||
|
||||
#ifndef NT_SUCCESS
|
||||
#define NT_SUCCESS(status) (((NTSTATUS)(status)) >= 0)
|
||||
#endif
|
||||
|
||||
#ifndef STATUS_SUCCESS
|
||||
#define STATUS_SUCCESS ((NTSTATUS) 0x00000000L)
|
||||
#endif
|
||||
|
||||
#ifndef STATUS_PENDING
|
||||
#define STATUS_PENDING ((NTSTATUS) 0x00000103L)
|
||||
#endif
|
||||
|
||||
#ifndef STATUS_CANCELLED
|
||||
#define STATUS_CANCELLED ((NTSTATUS) 0xC0000120L)
|
||||
#endif
|
||||
|
||||
typedef struct _IO_STATUS_BLOCK {
|
||||
NTSTATUS Status;
|
||||
ULONG_PTR Information;
|
||||
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
|
||||
|
||||
typedef VOID(NTAPI* PIO_APC_ROUTINE)(PVOID ApcContext,
|
||||
PIO_STATUS_BLOCK IoStatusBlock,
|
||||
ULONG Reserved);
|
||||
|
||||
typedef struct _LSA_UNICODE_STRING {
|
||||
USHORT Length;
|
||||
USHORT MaximumLength;
|
||||
PWSTR Buffer;
|
||||
} LSA_UNICODE_STRING, *PLSA_UNICODE_STRING, UNICODE_STRING, *PUNICODE_STRING;
|
||||
|
||||
#define RTL_CONSTANT_STRING(s) \
|
||||
{ sizeof(s) - sizeof((s)[0]), sizeof(s), s }
|
||||
|
||||
typedef struct _OBJECT_ATTRIBUTES {
|
||||
ULONG Length;
|
||||
HANDLE RootDirectory;
|
||||
PUNICODE_STRING ObjectName;
|
||||
ULONG Attributes;
|
||||
PVOID SecurityDescriptor;
|
||||
PVOID SecurityQualityOfService;
|
||||
} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;
|
||||
|
||||
#define RTL_CONSTANT_OBJECT_ATTRIBUTES(ObjectName, Attributes) \
|
||||
{ sizeof(OBJECT_ATTRIBUTES), NULL, ObjectName, Attributes, NULL, NULL }
|
||||
|
||||
#ifndef FILE_OPEN
|
||||
#define FILE_OPEN 0x00000001UL
|
||||
#endif
|
||||
|
||||
#define NT_NTDLL_IMPORT_LIST(X) \
|
||||
X(NTSTATUS, \
|
||||
NTAPI, \
|
||||
NtCreateFile, \
|
||||
(PHANDLE FileHandle, \
|
||||
ACCESS_MASK DesiredAccess, \
|
||||
POBJECT_ATTRIBUTES ObjectAttributes, \
|
||||
PIO_STATUS_BLOCK IoStatusBlock, \
|
||||
PLARGE_INTEGER AllocationSize, \
|
||||
ULONG FileAttributes, \
|
||||
ULONG ShareAccess, \
|
||||
ULONG CreateDisposition, \
|
||||
ULONG CreateOptions, \
|
||||
PVOID EaBuffer, \
|
||||
ULONG EaLength)) \
|
||||
\
|
||||
X(NTSTATUS, \
|
||||
NTAPI, \
|
||||
NtDeviceIoControlFile, \
|
||||
(HANDLE FileHandle, \
|
||||
HANDLE Event, \
|
||||
PIO_APC_ROUTINE ApcRoutine, \
|
||||
PVOID ApcContext, \
|
||||
PIO_STATUS_BLOCK IoStatusBlock, \
|
||||
ULONG IoControlCode, \
|
||||
PVOID InputBuffer, \
|
||||
ULONG InputBufferLength, \
|
||||
PVOID OutputBuffer, \
|
||||
ULONG OutputBufferLength)) \
|
||||
\
|
||||
X(ULONG, WINAPI, RtlNtStatusToDosError, (NTSTATUS Status)) \
|
||||
\
|
||||
X(NTSTATUS, \
|
||||
NTAPI, \
|
||||
NtCreateKeyedEvent, \
|
||||
(PHANDLE handle, \
|
||||
ACCESS_MASK access, \
|
||||
POBJECT_ATTRIBUTES attr, \
|
||||
ULONG flags)) \
|
||||
\
|
||||
X(NTSTATUS, \
|
||||
NTAPI, \
|
||||
NtWaitForKeyedEvent, \
|
||||
(HANDLE handle, PVOID key, BOOLEAN alertable, PLARGE_INTEGER mstimeout)) \
|
||||
\
|
||||
X(NTSTATUS, \
|
||||
NTAPI, \
|
||||
NtReleaseKeyedEvent, \
|
||||
(HANDLE handle, PVOID key, BOOLEAN alertable, PLARGE_INTEGER mstimeout))
|
||||
|
||||
#define X(return_type, attributes, name, parameters) \
|
||||
WEPOLL_INTERNAL_VAR return_type(attributes* name) parameters;
|
||||
NT_NTDLL_IMPORT_LIST(X)
|
||||
#undef X
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifndef _SSIZE_T_DEFINED
|
||||
typedef intptr_t ssize_t;
|
||||
#endif
|
||||
|
||||
#define array_count(a) (sizeof(a) / (sizeof((a)[0])))
|
||||
|
||||
/* clang-format off */
|
||||
#define container_of(ptr, type, member) \
|
||||
((type*) ((uintptr_t) (ptr) - offsetof(type, member)))
|
||||
/* clang-format on */
|
||||
|
||||
#define unused_var(v) ((void) (v))
|
||||
|
||||
/* Polyfill `inline` for older versions of msvc (up to Visual Studio 2013) */
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1900
|
||||
#define inline __inline
|
||||
#endif
|
||||
|
||||
/* clang-format off */
|
||||
#define AFD_POLL_RECEIVE 0x0001
|
||||
#define AFD_POLL_RECEIVE_EXPEDITED 0x0002
|
||||
#define AFD_POLL_SEND 0x0004
|
||||
#define AFD_POLL_DISCONNECT 0x0008
|
||||
#define AFD_POLL_ABORT 0x0010
|
||||
#define AFD_POLL_LOCAL_CLOSE 0x0020
|
||||
#define AFD_POLL_ACCEPT 0x0080
|
||||
#define AFD_POLL_CONNECT_FAIL 0x0100
|
||||
/* clang-format on */
|
||||
|
||||
typedef struct _AFD_POLL_HANDLE_INFO {
|
||||
HANDLE Handle;
|
||||
ULONG Events;
|
||||
NTSTATUS Status;
|
||||
} AFD_POLL_HANDLE_INFO, *PAFD_POLL_HANDLE_INFO;
|
||||
|
||||
typedef struct _AFD_POLL_INFO {
|
||||
LARGE_INTEGER Timeout;
|
||||
ULONG NumberOfHandles;
|
||||
ULONG Exclusive;
|
||||
AFD_POLL_HANDLE_INFO Handles[1];
|
||||
} AFD_POLL_INFO, *PAFD_POLL_INFO;
|
||||
|
||||
WEPOLL_INTERNAL int afd_create_helper_handle(HANDLE iocp,
|
||||
HANDLE* afd_helper_handle_out);
|
||||
|
||||
WEPOLL_INTERNAL int afd_poll(HANDLE afd_helper_handle,
|
||||
AFD_POLL_INFO* poll_info,
|
||||
OVERLAPPED* overlapped);
|
||||
|
||||
#define return_map_error(value) \
|
||||
do { \
|
||||
err_map_win_error(); \
|
||||
return (value); \
|
||||
} while (0)
|
||||
|
||||
#define return_set_error(value, error) \
|
||||
do { \
|
||||
err_set_win_error(error); \
|
||||
return (value); \
|
||||
} while (0)
|
||||
|
||||
WEPOLL_INTERNAL void err_map_win_error(void);
|
||||
WEPOLL_INTERNAL void err_set_win_error(DWORD error);
|
||||
WEPOLL_INTERNAL int err_check_handle(HANDLE handle);
|
||||
|
||||
WEPOLL_INTERNAL int ws_global_init(void);
|
||||
WEPOLL_INTERNAL SOCKET ws_get_base_socket(SOCKET socket);
|
||||
|
||||
#define IOCTL_AFD_POLL 0x00012024
|
||||
|
||||
static UNICODE_STRING afd__helper_name =
|
||||
RTL_CONSTANT_STRING(L"\\Device\\Afd\\Wepoll");
|
||||
|
||||
static OBJECT_ATTRIBUTES afd__helper_attributes =
|
||||
RTL_CONSTANT_OBJECT_ATTRIBUTES(&afd__helper_name, 0);
|
||||
|
||||
int afd_create_helper_handle(HANDLE iocp, HANDLE* afd_helper_handle_out) {
|
||||
HANDLE afd_helper_handle;
|
||||
IO_STATUS_BLOCK iosb;
|
||||
NTSTATUS status;
|
||||
|
||||
/* By opening \Device\Afd without specifying any extended attributes, we'll
|
||||
* get a handle that lets us talk to the AFD driver, but that doesn't have an
|
||||
* associated endpoint (so it's not a socket). */
|
||||
status = NtCreateFile(&afd_helper_handle,
|
||||
SYNCHRONIZE,
|
||||
&afd__helper_attributes,
|
||||
&iosb,
|
||||
NULL,
|
||||
0,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
FILE_OPEN,
|
||||
0,
|
||||
NULL,
|
||||
0);
|
||||
if (status != STATUS_SUCCESS)
|
||||
return_set_error(-1, RtlNtStatusToDosError(status));
|
||||
|
||||
if (CreateIoCompletionPort(afd_helper_handle, iocp, 0, 0) == NULL)
|
||||
goto error;
|
||||
|
||||
if (!SetFileCompletionNotificationModes(afd_helper_handle,
|
||||
FILE_SKIP_SET_EVENT_ON_HANDLE))
|
||||
goto error;
|
||||
|
||||
*afd_helper_handle_out = afd_helper_handle;
|
||||
return 0;
|
||||
|
||||
error:
|
||||
CloseHandle(afd_helper_handle);
|
||||
return_map_error(-1);
|
||||
}
|
||||
|
||||
int afd_poll(HANDLE afd_helper_handle,
|
||||
AFD_POLL_INFO* poll_info,
|
||||
OVERLAPPED* overlapped) {
|
||||
IO_STATUS_BLOCK* iosb;
|
||||
HANDLE event;
|
||||
void* apc_context;
|
||||
NTSTATUS status;
|
||||
|
||||
/* Blocking operation is not supported. */
|
||||
assert(overlapped != NULL);
|
||||
|
||||
iosb = (IO_STATUS_BLOCK*) &overlapped->Internal;
|
||||
event = overlapped->hEvent;
|
||||
|
||||
/* Do what other windows APIs would do: if hEvent has it's lowest bit set,
|
||||
* don't post a completion to the completion port. */
|
||||
if ((uintptr_t) event & 1) {
|
||||
event = (HANDLE)((uintptr_t) event & ~(uintptr_t) 1);
|
||||
apc_context = NULL;
|
||||
} else {
|
||||
apc_context = overlapped;
|
||||
}
|
||||
|
||||
iosb->Status = STATUS_PENDING;
|
||||
status = NtDeviceIoControlFile(afd_helper_handle,
|
||||
event,
|
||||
NULL,
|
||||
apc_context,
|
||||
iosb,
|
||||
IOCTL_AFD_POLL,
|
||||
poll_info,
|
||||
sizeof *poll_info,
|
||||
poll_info,
|
||||
sizeof *poll_info);
|
||||
|
||||
if (status == STATUS_SUCCESS)
|
||||
return 0;
|
||||
else if (status == STATUS_PENDING)
|
||||
return_set_error(-1, ERROR_IO_PENDING);
|
||||
else
|
||||
return_set_error(-1, RtlNtStatusToDosError(status));
|
||||
}
|
||||
|
||||
WEPOLL_INTERNAL int epoll_global_init(void);
|
||||
|
||||
WEPOLL_INTERNAL int init(void);
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct queue_node queue_node_t;
|
||||
|
||||
typedef struct queue_node {
|
||||
queue_node_t* prev;
|
||||
queue_node_t* next;
|
||||
} queue_node_t;
|
||||
|
||||
typedef struct queue {
|
||||
queue_node_t head;
|
||||
} queue_t;
|
||||
|
||||
WEPOLL_INTERNAL void queue_init(queue_t* queue);
|
||||
WEPOLL_INTERNAL void queue_node_init(queue_node_t* node);
|
||||
|
||||
WEPOLL_INTERNAL queue_node_t* queue_first(const queue_t* queue);
|
||||
WEPOLL_INTERNAL queue_node_t* queue_last(const queue_t* queue);
|
||||
|
||||
WEPOLL_INTERNAL void queue_prepend(queue_t* queue, queue_node_t* node);
|
||||
WEPOLL_INTERNAL void queue_append(queue_t* queue, queue_node_t* node);
|
||||
WEPOLL_INTERNAL void queue_move_first(queue_t* queue, queue_node_t* node);
|
||||
WEPOLL_INTERNAL void queue_move_last(queue_t* queue, queue_node_t* node);
|
||||
WEPOLL_INTERNAL void queue_remove(queue_node_t* node);
|
||||
|
||||
WEPOLL_INTERNAL bool queue_empty(const queue_t* queue);
|
||||
WEPOLL_INTERNAL bool queue_enqueued(const queue_node_t* node);
|
||||
|
||||
typedef struct port_state port_state_t;
|
||||
typedef struct poll_group poll_group_t;
|
||||
|
||||
WEPOLL_INTERNAL poll_group_t* poll_group_acquire(port_state_t* port);
|
||||
WEPOLL_INTERNAL void poll_group_release(poll_group_t* poll_group);
|
||||
|
||||
WEPOLL_INTERNAL void poll_group_delete(poll_group_t* poll_group);
|
||||
|
||||
WEPOLL_INTERNAL poll_group_t* poll_group_from_queue_node(
|
||||
queue_node_t* queue_node);
|
||||
WEPOLL_INTERNAL HANDLE
|
||||
poll_group_get_afd_helper_handle(poll_group_t* poll_group);
|
||||
|
||||
/* N.b.: the tree functions do not set errno or LastError when they fail. Each
|
||||
* of the API functions has at most one failure mode. It is up to the caller to
|
||||
* set an appropriate error code when necessary. */
|
||||
|
||||
typedef struct tree tree_t;
|
||||
typedef struct tree_node tree_node_t;
|
||||
|
||||
typedef struct tree {
|
||||
tree_node_t* root;
|
||||
} tree_t;
|
||||
|
||||
typedef struct tree_node {
|
||||
tree_node_t* left;
|
||||
tree_node_t* right;
|
||||
tree_node_t* parent;
|
||||
uintptr_t key;
|
||||
bool red;
|
||||
} tree_node_t;
|
||||
|
||||
WEPOLL_INTERNAL void tree_init(tree_t* tree);
|
||||
WEPOLL_INTERNAL void tree_node_init(tree_node_t* node);
|
||||
|
||||
WEPOLL_INTERNAL int tree_add(tree_t* tree, tree_node_t* node, uintptr_t key);
|
||||
WEPOLL_INTERNAL void tree_del(tree_t* tree, tree_node_t* node);
|
||||
|
||||
WEPOLL_INTERNAL tree_node_t* tree_find(const tree_t* tree, uintptr_t key);
|
||||
WEPOLL_INTERNAL tree_node_t* tree_root(const tree_t* tree);
|
||||
|
||||
typedef struct port_state port_state_t;
|
||||
typedef struct sock_state sock_state_t;
|
||||
|
||||
WEPOLL_INTERNAL sock_state_t* sock_new(port_state_t* port_state,
|
||||
SOCKET socket);
|
||||
WEPOLL_INTERNAL void sock_delete(port_state_t* port_state,
|
||||
sock_state_t* sock_state);
|
||||
WEPOLL_INTERNAL void sock_force_delete(port_state_t* port_state,
|
||||
sock_state_t* sock_state);
|
||||
|
||||
WEPOLL_INTERNAL int sock_set_event(port_state_t* port_state,
|
||||
sock_state_t* sock_state,
|
||||
const struct epoll_event* ev);
|
||||
|
||||
WEPOLL_INTERNAL int sock_update(port_state_t* port_state,
|
||||
sock_state_t* sock_state);
|
||||
WEPOLL_INTERNAL int sock_feed_event(port_state_t* port_state,
|
||||
OVERLAPPED* overlapped,
|
||||
struct epoll_event* ev);
|
||||
|
||||
WEPOLL_INTERNAL sock_state_t* sock_state_from_queue_node(
|
||||
queue_node_t* queue_node);
|
||||
WEPOLL_INTERNAL queue_node_t* sock_state_to_queue_node(
|
||||
sock_state_t* sock_state);
|
||||
WEPOLL_INTERNAL sock_state_t* sock_state_from_tree_node(
|
||||
tree_node_t* tree_node);
|
||||
WEPOLL_INTERNAL tree_node_t* sock_state_to_tree_node(sock_state_t* sock_state);
|
||||
|
||||
/* The reflock is a special kind of lock that normally prevents a chunk of
|
||||
* memory from being freed, but does allow the chunk of memory to eventually be
|
||||
* released in a coordinated fashion.
|
||||
*
|
||||
* Under normal operation, threads increase and decrease the reference count,
|
||||
* which are wait-free operations.
|
||||
*
|
||||
* Exactly once during the reflock's lifecycle, a thread holding a reference to
|
||||
* the lock may "destroy" the lock; this operation blocks until all other
|
||||
* threads holding a reference to the lock have dereferenced it. After
|
||||
* "destroy" returns, the calling thread may assume that no other threads have
|
||||
* a reference to the lock.
|
||||
*
|
||||
* Attemmpting to lock or destroy a lock after reflock_unref_and_destroy() has
|
||||
* been called is invalid and results in undefined behavior. Therefore the user
|
||||
* should use another lock to guarantee that this can't happen.
|
||||
*/
|
||||
|
||||
typedef struct reflock {
|
||||
volatile long state; /* 32-bit Interlocked APIs operate on `long` values. */
|
||||
} reflock_t;
|
||||
|
||||
WEPOLL_INTERNAL int reflock_global_init(void);
|
||||
|
||||
WEPOLL_INTERNAL void reflock_init(reflock_t* reflock);
|
||||
WEPOLL_INTERNAL void reflock_ref(reflock_t* reflock);
|
||||
WEPOLL_INTERNAL void reflock_unref(reflock_t* reflock);
|
||||
WEPOLL_INTERNAL void reflock_unref_and_destroy(reflock_t* reflock);
|
||||
|
||||
typedef struct ts_tree {
|
||||
tree_t tree;
|
||||
SRWLOCK lock;
|
||||
} ts_tree_t;
|
||||
|
||||
typedef struct ts_tree_node {
|
||||
tree_node_t tree_node;
|
||||
reflock_t reflock;
|
||||
} ts_tree_node_t;
|
||||
|
||||
WEPOLL_INTERNAL void ts_tree_init(ts_tree_t* rtl);
|
||||
WEPOLL_INTERNAL void ts_tree_node_init(ts_tree_node_t* node);
|
||||
|
||||
WEPOLL_INTERNAL int ts_tree_add(ts_tree_t* ts_tree,
|
||||
ts_tree_node_t* node,
|
||||
uintptr_t key);
|
||||
|
||||
WEPOLL_INTERNAL ts_tree_node_t* ts_tree_del_and_ref(ts_tree_t* ts_tree,
|
||||
uintptr_t key);
|
||||
WEPOLL_INTERNAL ts_tree_node_t* ts_tree_find_and_ref(ts_tree_t* ts_tree,
|
||||
uintptr_t key);
|
||||
|
||||
WEPOLL_INTERNAL void ts_tree_node_unref(ts_tree_node_t* node);
|
||||
WEPOLL_INTERNAL void ts_tree_node_unref_and_destroy(ts_tree_node_t* node);
|
||||
|
||||
typedef struct port_state port_state_t;
|
||||
typedef struct sock_state sock_state_t;
|
||||
|
||||
typedef struct port_state {
|
||||
HANDLE iocp;
|
||||
tree_t sock_tree;
|
||||
queue_t sock_update_queue;
|
||||
queue_t sock_deleted_queue;
|
||||
queue_t poll_group_queue;
|
||||
ts_tree_node_t handle_tree_node;
|
||||
CRITICAL_SECTION lock;
|
||||
size_t active_poll_count;
|
||||
} port_state_t;
|
||||
|
||||
WEPOLL_INTERNAL port_state_t* port_new(HANDLE* iocp_out);
|
||||
WEPOLL_INTERNAL int port_close(port_state_t* port_state);
|
||||
WEPOLL_INTERNAL int port_delete(port_state_t* port_state);
|
||||
|
||||
WEPOLL_INTERNAL int port_wait(port_state_t* port_state,
|
||||
struct epoll_event* events,
|
||||
int maxevents,
|
||||
int timeout);
|
||||
|
||||
WEPOLL_INTERNAL int port_ctl(port_state_t* port_state,
|
||||
int op,
|
||||
SOCKET sock,
|
||||
struct epoll_event* ev);
|
||||
|
||||
WEPOLL_INTERNAL int port_register_socket_handle(port_state_t* port_state,
|
||||
sock_state_t* sock_state,
|
||||
SOCKET socket);
|
||||
WEPOLL_INTERNAL void port_unregister_socket_handle(port_state_t* port_state,
|
||||
sock_state_t* sock_state);
|
||||
WEPOLL_INTERNAL sock_state_t* port_find_socket(port_state_t* port_state,
|
||||
SOCKET socket);
|
||||
|
||||
WEPOLL_INTERNAL void port_request_socket_update(port_state_t* port_state,
|
||||
sock_state_t* sock_state);
|
||||
WEPOLL_INTERNAL void port_cancel_socket_update(port_state_t* port_state,
|
||||
sock_state_t* sock_state);
|
||||
|
||||
WEPOLL_INTERNAL void port_add_deleted_socket(port_state_t* port_state,
|
||||
sock_state_t* sock_state);
|
||||
WEPOLL_INTERNAL void port_remove_deleted_socket(port_state_t* port_state,
|
||||
sock_state_t* sock_state);
|
||||
|
||||
static ts_tree_t epoll__handle_tree;
|
||||
|
||||
static inline port_state_t* epoll__handle_tree_node_to_port(
|
||||
ts_tree_node_t* tree_node) {
|
||||
return container_of(tree_node, port_state_t, handle_tree_node);
|
||||
}
|
||||
|
||||
int epoll_global_init(void) {
|
||||
ts_tree_init(&epoll__handle_tree);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static HANDLE epoll__create(void) {
|
||||
port_state_t* port_state;
|
||||
HANDLE ephnd;
|
||||
|
||||
if (init() < 0)
|
||||
return NULL;
|
||||
|
||||
port_state = port_new(&ephnd);
|
||||
if (port_state == NULL)
|
||||
return NULL;
|
||||
|
||||
if (ts_tree_add(&epoll__handle_tree,
|
||||
&port_state->handle_tree_node,
|
||||
(uintptr_t) ephnd) < 0) {
|
||||
/* This should never happen. */
|
||||
port_delete(port_state);
|
||||
return_set_error(NULL, ERROR_ALREADY_EXISTS);
|
||||
}
|
||||
|
||||
return ephnd;
|
||||
}
|
||||
|
||||
HANDLE epoll_create(int size) {
|
||||
if (size <= 0)
|
||||
return_set_error(NULL, ERROR_INVALID_PARAMETER);
|
||||
|
||||
return epoll__create();
|
||||
}
|
||||
|
||||
HANDLE epoll_create1(int flags) {
|
||||
if (flags != 0)
|
||||
return_set_error(NULL, ERROR_INVALID_PARAMETER);
|
||||
|
||||
return epoll__create();
|
||||
}
|
||||
|
||||
int epoll_close(HANDLE ephnd) {
|
||||
ts_tree_node_t* tree_node;
|
||||
port_state_t* port_state;
|
||||
|
||||
if (init() < 0)
|
||||
return -1;
|
||||
|
||||
tree_node = ts_tree_del_and_ref(&epoll__handle_tree, (uintptr_t) ephnd);
|
||||
if (tree_node == NULL) {
|
||||
err_set_win_error(ERROR_INVALID_PARAMETER);
|
||||
goto err;
|
||||
}
|
||||
|
||||
port_state = epoll__handle_tree_node_to_port(tree_node);
|
||||
port_close(port_state);
|
||||
|
||||
ts_tree_node_unref_and_destroy(tree_node);
|
||||
|
||||
return port_delete(port_state);
|
||||
|
||||
err:
|
||||
err_check_handle(ephnd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int epoll_ctl(HANDLE ephnd, int op, SOCKET sock, struct epoll_event* ev) {
|
||||
ts_tree_node_t* tree_node;
|
||||
port_state_t* port_state;
|
||||
int r;
|
||||
|
||||
if (init() < 0)
|
||||
return -1;
|
||||
|
||||
tree_node = ts_tree_find_and_ref(&epoll__handle_tree, (uintptr_t) ephnd);
|
||||
if (tree_node == NULL) {
|
||||
err_set_win_error(ERROR_INVALID_PARAMETER);
|
||||
goto err;
|
||||
}
|
||||
|
||||
port_state = epoll__handle_tree_node_to_port(tree_node);
|
||||
r = port_ctl(port_state, op, sock, ev);
|
||||
|
||||
ts_tree_node_unref(tree_node);
|
||||
|
||||
if (r < 0)
|
||||
goto err;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
/* On Linux, in the case of epoll_ctl_mod(), EBADF takes priority over other
|
||||
* errors. Wepoll mimics this behavior. */
|
||||
err_check_handle(ephnd);
|
||||
err_check_handle((HANDLE) sock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int epoll_wait(HANDLE ephnd,
|
||||
struct epoll_event* events,
|
||||
int maxevents,
|
||||
int timeout) {
|
||||
ts_tree_node_t* tree_node;
|
||||
port_state_t* port_state;
|
||||
int num_events;
|
||||
|
||||
if (maxevents <= 0)
|
||||
return_set_error(-1, ERROR_INVALID_PARAMETER);
|
||||
|
||||
if (init() < 0)
|
||||
return -1;
|
||||
|
||||
tree_node = ts_tree_find_and_ref(&epoll__handle_tree, (uintptr_t) ephnd);
|
||||
if (tree_node == NULL) {
|
||||
err_set_win_error(ERROR_INVALID_PARAMETER);
|
||||
goto err;
|
||||
}
|
||||
|
||||
port_state = epoll__handle_tree_node_to_port(tree_node);
|
||||
num_events = port_wait(port_state, events, maxevents, timeout);
|
||||
|
||||
ts_tree_node_unref(tree_node);
|
||||
|
||||
if (num_events < 0)
|
||||
goto err;
|
||||
|
||||
return num_events;
|
||||
|
||||
err:
|
||||
err_check_handle(ephnd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#define ERR__ERRNO_MAPPINGS(X) \
|
||||
X(ERROR_ACCESS_DENIED, EACCES) \
|
||||
X(ERROR_ALREADY_EXISTS, EEXIST) \
|
||||
X(ERROR_BAD_COMMAND, EACCES) \
|
||||
X(ERROR_BAD_EXE_FORMAT, ENOEXEC) \
|
||||
X(ERROR_BAD_LENGTH, EACCES) \
|
||||
X(ERROR_BAD_NETPATH, ENOENT) \
|
||||
X(ERROR_BAD_NET_NAME, ENOENT) \
|
||||
X(ERROR_BAD_NET_RESP, ENETDOWN) \
|
||||
X(ERROR_BAD_PATHNAME, ENOENT) \
|
||||
X(ERROR_BROKEN_PIPE, EPIPE) \
|
||||
X(ERROR_CANNOT_MAKE, EACCES) \
|
||||
X(ERROR_COMMITMENT_LIMIT, ENOMEM) \
|
||||
X(ERROR_CONNECTION_ABORTED, ECONNABORTED) \
|
||||
X(ERROR_CONNECTION_ACTIVE, EISCONN) \
|
||||
X(ERROR_CONNECTION_REFUSED, ECONNREFUSED) \
|
||||
X(ERROR_CRC, EACCES) \
|
||||
X(ERROR_DIR_NOT_EMPTY, ENOTEMPTY) \
|
||||
X(ERROR_DISK_FULL, ENOSPC) \
|
||||
X(ERROR_DUP_NAME, EADDRINUSE) \
|
||||
X(ERROR_FILENAME_EXCED_RANGE, ENOENT) \
|
||||
X(ERROR_FILE_NOT_FOUND, ENOENT) \
|
||||
X(ERROR_GEN_FAILURE, EACCES) \
|
||||
X(ERROR_GRACEFUL_DISCONNECT, EPIPE) \
|
||||
X(ERROR_HOST_DOWN, EHOSTUNREACH) \
|
||||
X(ERROR_HOST_UNREACHABLE, EHOSTUNREACH) \
|
||||
X(ERROR_INSUFFICIENT_BUFFER, EFAULT) \
|
||||
X(ERROR_INVALID_ADDRESS, EADDRNOTAVAIL) \
|
||||
X(ERROR_INVALID_FUNCTION, EINVAL) \
|
||||
X(ERROR_INVALID_HANDLE, EBADF) \
|
||||
X(ERROR_INVALID_NETNAME, EADDRNOTAVAIL) \
|
||||
X(ERROR_INVALID_PARAMETER, EINVAL) \
|
||||
X(ERROR_INVALID_USER_BUFFER, EMSGSIZE) \
|
||||
X(ERROR_IO_PENDING, EINPROGRESS) \
|
||||
X(ERROR_LOCK_VIOLATION, EACCES) \
|
||||
X(ERROR_MORE_DATA, EMSGSIZE) \
|
||||
X(ERROR_NETNAME_DELETED, ECONNABORTED) \
|
||||
X(ERROR_NETWORK_ACCESS_DENIED, EACCES) \
|
||||
X(ERROR_NETWORK_BUSY, ENETDOWN) \
|
||||
X(ERROR_NETWORK_UNREACHABLE, ENETUNREACH) \
|
||||
X(ERROR_NOACCESS, EFAULT) \
|
||||
X(ERROR_NONPAGED_SYSTEM_RESOURCES, ENOMEM) \
|
||||
X(ERROR_NOT_ENOUGH_MEMORY, ENOMEM) \
|
||||
X(ERROR_NOT_ENOUGH_QUOTA, ENOMEM) \
|
||||
X(ERROR_NOT_FOUND, ENOENT) \
|
||||
X(ERROR_NOT_LOCKED, EACCES) \
|
||||
X(ERROR_NOT_READY, EACCES) \
|
||||
X(ERROR_NOT_SAME_DEVICE, EXDEV) \
|
||||
X(ERROR_NOT_SUPPORTED, ENOTSUP) \
|
||||
X(ERROR_NO_MORE_FILES, ENOENT) \
|
||||
X(ERROR_NO_SYSTEM_RESOURCES, ENOMEM) \
|
||||
X(ERROR_OPERATION_ABORTED, EINTR) \
|
||||
X(ERROR_OUT_OF_PAPER, EACCES) \
|
||||
X(ERROR_PAGED_SYSTEM_RESOURCES, ENOMEM) \
|
||||
X(ERROR_PAGEFILE_QUOTA, ENOMEM) \
|
||||
X(ERROR_PATH_NOT_FOUND, ENOENT) \
|
||||
X(ERROR_PIPE_NOT_CONNECTED, EPIPE) \
|
||||
X(ERROR_PORT_UNREACHABLE, ECONNRESET) \
|
||||
X(ERROR_PROTOCOL_UNREACHABLE, ENETUNREACH) \
|
||||
X(ERROR_REM_NOT_LIST, ECONNREFUSED) \
|
||||
X(ERROR_REQUEST_ABORTED, EINTR) \
|
||||
X(ERROR_REQ_NOT_ACCEP, EWOULDBLOCK) \
|
||||
X(ERROR_SECTOR_NOT_FOUND, EACCES) \
|
||||
X(ERROR_SEM_TIMEOUT, ETIMEDOUT) \
|
||||
X(ERROR_SHARING_VIOLATION, EACCES) \
|
||||
X(ERROR_TOO_MANY_NAMES, ENOMEM) \
|
||||
X(ERROR_TOO_MANY_OPEN_FILES, EMFILE) \
|
||||
X(ERROR_UNEXP_NET_ERR, ECONNABORTED) \
|
||||
X(ERROR_WAIT_NO_CHILDREN, ECHILD) \
|
||||
X(ERROR_WORKING_SET_QUOTA, ENOMEM) \
|
||||
X(ERROR_WRITE_PROTECT, EACCES) \
|
||||
X(ERROR_WRONG_DISK, EACCES) \
|
||||
X(WSAEACCES, EACCES) \
|
||||
X(WSAEADDRINUSE, EADDRINUSE) \
|
||||
X(WSAEADDRNOTAVAIL, EADDRNOTAVAIL) \
|
||||
X(WSAEAFNOSUPPORT, EAFNOSUPPORT) \
|
||||
X(WSAECONNABORTED, ECONNABORTED) \
|
||||
X(WSAECONNREFUSED, ECONNREFUSED) \
|
||||
X(WSAECONNRESET, ECONNRESET) \
|
||||
X(WSAEDISCON, EPIPE) \
|
||||
X(WSAEFAULT, EFAULT) \
|
||||
X(WSAEHOSTDOWN, EHOSTUNREACH) \
|
||||
X(WSAEHOSTUNREACH, EHOSTUNREACH) \
|
||||
X(WSAEINPROGRESS, EBUSY) \
|
||||
X(WSAEINTR, EINTR) \
|
||||
X(WSAEINVAL, EINVAL) \
|
||||
X(WSAEISCONN, EISCONN) \
|
||||
X(WSAEMSGSIZE, EMSGSIZE) \
|
||||
X(WSAENETDOWN, ENETDOWN) \
|
||||
X(WSAENETRESET, EHOSTUNREACH) \
|
||||
X(WSAENETUNREACH, ENETUNREACH) \
|
||||
X(WSAENOBUFS, ENOMEM) \
|
||||
X(WSAENOTCONN, ENOTCONN) \
|
||||
X(WSAENOTSOCK, ENOTSOCK) \
|
||||
X(WSAEOPNOTSUPP, EOPNOTSUPP) \
|
||||
X(WSAEPROCLIM, ENOMEM) \
|
||||
X(WSAESHUTDOWN, EPIPE) \
|
||||
X(WSAETIMEDOUT, ETIMEDOUT) \
|
||||
X(WSAEWOULDBLOCK, EWOULDBLOCK) \
|
||||
X(WSANOTINITIALISED, ENETDOWN) \
|
||||
X(WSASYSNOTREADY, ENETDOWN) \
|
||||
X(WSAVERNOTSUPPORTED, ENOSYS)
|
||||
|
||||
static errno_t err__map_win_error_to_errno(DWORD error) {
|
||||
switch (error) {
|
||||
#define X(error_sym, errno_sym) \
|
||||
case error_sym: \
|
||||
return errno_sym;
|
||||
ERR__ERRNO_MAPPINGS(X)
|
||||
#undef X
|
||||
}
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
void err_map_win_error(void) {
|
||||
errno = err__map_win_error_to_errno(GetLastError());
|
||||
}
|
||||
|
||||
void err_set_win_error(DWORD error) {
|
||||
SetLastError(error);
|
||||
errno = err__map_win_error_to_errno(error);
|
||||
}
|
||||
|
||||
int err_check_handle(HANDLE handle) {
|
||||
DWORD flags;
|
||||
|
||||
/* GetHandleInformation() succeeds when passed INVALID_HANDLE_VALUE, so check
|
||||
* for this condition explicitly. */
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
return_set_error(-1, ERROR_INVALID_HANDLE);
|
||||
|
||||
if (!GetHandleInformation(handle, &flags))
|
||||
return_map_error(-1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool init__done = false;
|
||||
static INIT_ONCE init__once = INIT_ONCE_STATIC_INIT;
|
||||
|
||||
static BOOL CALLBACK init__once_callback(INIT_ONCE* once,
|
||||
void* parameter,
|
||||
void** context) {
|
||||
unused_var(once);
|
||||
unused_var(parameter);
|
||||
unused_var(context);
|
||||
|
||||
/* N.b. that initialization order matters here. */
|
||||
if (ws_global_init() < 0 || nt_global_init() < 0 ||
|
||||
reflock_global_init() < 0 || epoll_global_init() < 0)
|
||||
return FALSE;
|
||||
|
||||
init__done = true;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int init(void) {
|
||||
if (!init__done &&
|
||||
!InitOnceExecuteOnce(&init__once, init__once_callback, NULL, NULL))
|
||||
return -1; /* LastError and errno aren't touched InitOnceExecuteOnce. */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set up a workaround for the following problem:
|
||||
* FARPROC addr = GetProcAddress(...);
|
||||
* MY_FUNC func = (MY_FUNC) addr; <-- GCC 8 warning/error.
|
||||
* MY_FUNC func = (MY_FUNC) (void*) addr; <-- MSVC warning/error.
|
||||
* To compile cleanly with either compiler, do casts with this "bridge" type:
|
||||
* MY_FUNC func = (MY_FUNC) (nt__fn_ptr_cast_t) addr; */
|
||||
#ifdef __GNUC__
|
||||
typedef void* nt__fn_ptr_cast_t;
|
||||
#else
|
||||
typedef FARPROC nt__fn_ptr_cast_t;
|
||||
#endif
|
||||
|
||||
#define X(return_type, attributes, name, parameters) \
|
||||
WEPOLL_INTERNAL return_type(attributes* name) parameters = NULL;
|
||||
NT_NTDLL_IMPORT_LIST(X)
|
||||
#undef X
|
||||
|
||||
int nt_global_init(void) {
|
||||
HMODULE ntdll;
|
||||
FARPROC fn_ptr;
|
||||
|
||||
ntdll = GetModuleHandleW(L"ntdll.dll");
|
||||
if (ntdll == NULL)
|
||||
return -1;
|
||||
|
||||
#define X(return_type, attributes, name, parameters) \
|
||||
fn_ptr = GetProcAddress(ntdll, #name); \
|
||||
if (fn_ptr == NULL) \
|
||||
return -1; \
|
||||
name = (return_type(attributes*) parameters)(nt__fn_ptr_cast_t) fn_ptr;
|
||||
NT_NTDLL_IMPORT_LIST(X)
|
||||
#undef X
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <string.h>
|
||||
|
||||
static const size_t POLL_GROUP__MAX_GROUP_SIZE = 32;
|
||||
|
||||
typedef struct poll_group {
|
||||
port_state_t* port_state;
|
||||
queue_node_t queue_node;
|
||||
HANDLE afd_helper_handle;
|
||||
size_t group_size;
|
||||
} poll_group_t;
|
||||
|
||||
static poll_group_t* poll_group__new(port_state_t* port_state) {
|
||||
poll_group_t* poll_group = malloc(sizeof *poll_group);
|
||||
if (poll_group == NULL)
|
||||
return_set_error(NULL, ERROR_NOT_ENOUGH_MEMORY);
|
||||
|
||||
memset(poll_group, 0, sizeof *poll_group);
|
||||
|
||||
queue_node_init(&poll_group->queue_node);
|
||||
poll_group->port_state = port_state;
|
||||
|
||||
if (afd_create_helper_handle(port_state->iocp,
|
||||
&poll_group->afd_helper_handle) < 0) {
|
||||
free(poll_group);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
queue_append(&port_state->poll_group_queue, &poll_group->queue_node);
|
||||
|
||||
return poll_group;
|
||||
}
|
||||
|
||||
void poll_group_delete(poll_group_t* poll_group) {
|
||||
assert(poll_group->group_size == 0);
|
||||
CloseHandle(poll_group->afd_helper_handle);
|
||||
queue_remove(&poll_group->queue_node);
|
||||
free(poll_group);
|
||||
}
|
||||
|
||||
poll_group_t* poll_group_from_queue_node(queue_node_t* queue_node) {
|
||||
return container_of(queue_node, poll_group_t, queue_node);
|
||||
}
|
||||
|
||||
HANDLE poll_group_get_afd_helper_handle(poll_group_t* poll_group) {
|
||||
return poll_group->afd_helper_handle;
|
||||
}
|
||||
|
||||
poll_group_t* poll_group_acquire(port_state_t* port_state) {
|
||||
queue_t* queue = &port_state->poll_group_queue;
|
||||
poll_group_t* poll_group =
|
||||
!queue_empty(queue)
|
||||
? container_of(queue_last(queue), poll_group_t, queue_node)
|
||||
: NULL;
|
||||
|
||||
if (poll_group == NULL ||
|
||||
poll_group->group_size >= POLL_GROUP__MAX_GROUP_SIZE)
|
||||
poll_group = poll_group__new(port_state);
|
||||
if (poll_group == NULL)
|
||||
return NULL;
|
||||
|
||||
if (++poll_group->group_size == POLL_GROUP__MAX_GROUP_SIZE)
|
||||
queue_move_first(&port_state->poll_group_queue, &poll_group->queue_node);
|
||||
|
||||
return poll_group;
|
||||
}
|
||||
|
||||
void poll_group_release(poll_group_t* poll_group) {
|
||||
port_state_t* port_state = poll_group->port_state;
|
||||
|
||||
poll_group->group_size--;
|
||||
assert(poll_group->group_size < POLL_GROUP__MAX_GROUP_SIZE);
|
||||
|
||||
queue_move_last(&port_state->poll_group_queue, &poll_group->queue_node);
|
||||
|
||||
/* Poll groups are currently only freed when the epoll port is closed. */
|
||||
}
|
||||
|
||||
#define PORT__MAX_ON_STACK_COMPLETIONS 256
|
||||
|
||||
static port_state_t* port__alloc(void) {
|
||||
port_state_t* port_state = malloc(sizeof *port_state);
|
||||
if (port_state == NULL)
|
||||
return_set_error(NULL, ERROR_NOT_ENOUGH_MEMORY);
|
||||
|
||||
return port_state;
|
||||
}
|
||||
|
||||
static void port__free(port_state_t* port) {
|
||||
assert(port != NULL);
|
||||
free(port);
|
||||
}
|
||||
|
||||
static HANDLE port__create_iocp(void) {
|
||||
HANDLE iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
|
||||
if (iocp == NULL)
|
||||
return_map_error(NULL);
|
||||
|
||||
return iocp;
|
||||
}
|
||||
|
||||
port_state_t* port_new(HANDLE* iocp_out) {
|
||||
port_state_t* port_state;
|
||||
HANDLE iocp;
|
||||
|
||||
port_state = port__alloc();
|
||||
if (port_state == NULL)
|
||||
goto err1;
|
||||
|
||||
iocp = port__create_iocp();
|
||||
if (iocp == NULL)
|
||||
goto err2;
|
||||
|
||||
memset(port_state, 0, sizeof *port_state);
|
||||
|
||||
port_state->iocp = iocp;
|
||||
tree_init(&port_state->sock_tree);
|
||||
queue_init(&port_state->sock_update_queue);
|
||||
queue_init(&port_state->sock_deleted_queue);
|
||||
queue_init(&port_state->poll_group_queue);
|
||||
ts_tree_node_init(&port_state->handle_tree_node);
|
||||
InitializeCriticalSection(&port_state->lock);
|
||||
|
||||
*iocp_out = iocp;
|
||||
return port_state;
|
||||
|
||||
err2:
|
||||
port__free(port_state);
|
||||
err1:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int port__close_iocp(port_state_t* port_state) {
|
||||
HANDLE iocp = port_state->iocp;
|
||||
port_state->iocp = NULL;
|
||||
|
||||
if (!CloseHandle(iocp))
|
||||
return_map_error(-1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int port_close(port_state_t* port_state) {
|
||||
int result;
|
||||
|
||||
EnterCriticalSection(&port_state->lock);
|
||||
result = port__close_iocp(port_state);
|
||||
LeaveCriticalSection(&port_state->lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int port_delete(port_state_t* port_state) {
|
||||
tree_node_t* tree_node;
|
||||
queue_node_t* queue_node;
|
||||
|
||||
/* At this point the IOCP port should have been closed. */
|
||||
assert(port_state->iocp == NULL);
|
||||
|
||||
while ((tree_node = tree_root(&port_state->sock_tree)) != NULL) {
|
||||
sock_state_t* sock_state = sock_state_from_tree_node(tree_node);
|
||||
sock_force_delete(port_state, sock_state);
|
||||
}
|
||||
|
||||
while ((queue_node = queue_first(&port_state->sock_deleted_queue)) != NULL) {
|
||||
sock_state_t* sock_state = sock_state_from_queue_node(queue_node);
|
||||
sock_force_delete(port_state, sock_state);
|
||||
}
|
||||
|
||||
while ((queue_node = queue_first(&port_state->poll_group_queue)) != NULL) {
|
||||
poll_group_t* poll_group = poll_group_from_queue_node(queue_node);
|
||||
poll_group_delete(poll_group);
|
||||
}
|
||||
|
||||
assert(queue_empty(&port_state->sock_update_queue));
|
||||
|
||||
DeleteCriticalSection(&port_state->lock);
|
||||
|
||||
port__free(port_state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int port__update_events(port_state_t* port_state) {
|
||||
queue_t* sock_update_queue = &port_state->sock_update_queue;
|
||||
|
||||
/* Walk the queue, submitting new poll requests for every socket that needs
|
||||
* it. */
|
||||
while (!queue_empty(sock_update_queue)) {
|
||||
queue_node_t* queue_node = queue_first(sock_update_queue);
|
||||
sock_state_t* sock_state = sock_state_from_queue_node(queue_node);
|
||||
|
||||
if (sock_update(port_state, sock_state) < 0)
|
||||
return -1;
|
||||
|
||||
/* sock_update() removes the socket from the update queue. */
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void port__update_events_if_polling(port_state_t* port_state) {
|
||||
if (port_state->active_poll_count > 0)
|
||||
port__update_events(port_state);
|
||||
}
|
||||
|
||||
static int port__feed_events(port_state_t* port_state,
|
||||
struct epoll_event* epoll_events,
|
||||
OVERLAPPED_ENTRY* iocp_events,
|
||||
DWORD iocp_event_count) {
|
||||
int epoll_event_count = 0;
|
||||
DWORD i;
|
||||
|
||||
for (i = 0; i < iocp_event_count; i++) {
|
||||
OVERLAPPED* overlapped = iocp_events[i].lpOverlapped;
|
||||
struct epoll_event* ev = &epoll_events[epoll_event_count];
|
||||
|
||||
epoll_event_count += sock_feed_event(port_state, overlapped, ev);
|
||||
}
|
||||
|
||||
return epoll_event_count;
|
||||
}
|
||||
|
||||
static int port__poll(port_state_t* port_state,
|
||||
struct epoll_event* epoll_events,
|
||||
OVERLAPPED_ENTRY* iocp_events,
|
||||
DWORD maxevents,
|
||||
DWORD timeout) {
|
||||
DWORD completion_count;
|
||||
|
||||
if (port__update_events(port_state) < 0)
|
||||
return -1;
|
||||
|
||||
port_state->active_poll_count++;
|
||||
|
||||
LeaveCriticalSection(&port_state->lock);
|
||||
|
||||
BOOL r = GetQueuedCompletionStatusEx(port_state->iocp,
|
||||
iocp_events,
|
||||
maxevents,
|
||||
&completion_count,
|
||||
timeout,
|
||||
FALSE);
|
||||
|
||||
EnterCriticalSection(&port_state->lock);
|
||||
|
||||
port_state->active_poll_count--;
|
||||
|
||||
if (!r)
|
||||
return_map_error(-1);
|
||||
|
||||
return port__feed_events(
|
||||
port_state, epoll_events, iocp_events, completion_count);
|
||||
}
|
||||
|
||||
int port_wait(port_state_t* port_state,
|
||||
struct epoll_event* events,
|
||||
int maxevents,
|
||||
int timeout) {
|
||||
OVERLAPPED_ENTRY stack_iocp_events[PORT__MAX_ON_STACK_COMPLETIONS];
|
||||
OVERLAPPED_ENTRY* iocp_events;
|
||||
uint64_t due = 0;
|
||||
DWORD gqcs_timeout;
|
||||
int result;
|
||||
|
||||
/* Check whether `maxevents` is in range. */
|
||||
if (maxevents <= 0)
|
||||
return_set_error(-1, ERROR_INVALID_PARAMETER);
|
||||
|
||||
/* Decide whether the IOCP completion list can live on the stack, or allocate
|
||||
* memory for it on the heap. */
|
||||
if ((size_t) maxevents <= array_count(stack_iocp_events)) {
|
||||
iocp_events = stack_iocp_events;
|
||||
} else if ((iocp_events =
|
||||
malloc((size_t) maxevents * sizeof *iocp_events)) == NULL) {
|
||||
iocp_events = stack_iocp_events;
|
||||
maxevents = array_count(stack_iocp_events);
|
||||
}
|
||||
|
||||
/* Compute the timeout for GetQueuedCompletionStatus, and the wait end
|
||||
* time, if the user specified a timeout other than zero or infinite. */
|
||||
if (timeout > 0) {
|
||||
due = GetTickCount64() + (uint64_t) timeout;
|
||||
gqcs_timeout = (DWORD) timeout;
|
||||
} else if (timeout == 0) {
|
||||
gqcs_timeout = 0;
|
||||
} else {
|
||||
gqcs_timeout = INFINITE;
|
||||
}
|
||||
|
||||
EnterCriticalSection(&port_state->lock);
|
||||
|
||||
/* Dequeue completion packets until either at least one interesting event
|
||||
* has been discovered, or the timeout is reached. */
|
||||
for (;;) {
|
||||
uint64_t now;
|
||||
|
||||
result = port__poll(
|
||||
port_state, events, iocp_events, (DWORD) maxevents, gqcs_timeout);
|
||||
if (result < 0 || result > 0)
|
||||
break; /* Result, error, or time-out. */
|
||||
|
||||
if (timeout < 0)
|
||||
continue; /* When timeout is negative, never time out. */
|
||||
|
||||
/* Update time. */
|
||||
now = GetTickCount64();
|
||||
|
||||
/* Do not allow the due time to be in the past. */
|
||||
if (now >= due) {
|
||||
SetLastError(WAIT_TIMEOUT);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Recompute time-out argument for GetQueuedCompletionStatus. */
|
||||
gqcs_timeout = (DWORD)(due - now);
|
||||
}
|
||||
|
||||
port__update_events_if_polling(port_state);
|
||||
|
||||
LeaveCriticalSection(&port_state->lock);
|
||||
|
||||
if (iocp_events != stack_iocp_events)
|
||||
free(iocp_events);
|
||||
|
||||
if (result >= 0)
|
||||
return result;
|
||||
else if (GetLastError() == WAIT_TIMEOUT)
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int port__ctl_add(port_state_t* port_state,
|
||||
SOCKET sock,
|
||||
struct epoll_event* ev) {
|
||||
sock_state_t* sock_state = sock_new(port_state, sock);
|
||||
if (sock_state == NULL)
|
||||
return -1;
|
||||
|
||||
if (sock_set_event(port_state, sock_state, ev) < 0) {
|
||||
sock_delete(port_state, sock_state);
|
||||
return -1;
|
||||
}
|
||||
|
||||
port__update_events_if_polling(port_state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int port__ctl_mod(port_state_t* port_state,
|
||||
SOCKET sock,
|
||||
struct epoll_event* ev) {
|
||||
sock_state_t* sock_state = port_find_socket(port_state, sock);
|
||||
if (sock_state == NULL)
|
||||
return -1;
|
||||
|
||||
if (sock_set_event(port_state, sock_state, ev) < 0)
|
||||
return -1;
|
||||
|
||||
port__update_events_if_polling(port_state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int port__ctl_del(port_state_t* port_state, SOCKET sock) {
|
||||
sock_state_t* sock_state = port_find_socket(port_state, sock);
|
||||
if (sock_state == NULL)
|
||||
return -1;
|
||||
|
||||
sock_delete(port_state, sock_state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int port__ctl_op(port_state_t* port_state,
|
||||
int op,
|
||||
SOCKET sock,
|
||||
struct epoll_event* ev) {
|
||||
switch (op) {
|
||||
case EPOLL_CTL_ADD:
|
||||
return port__ctl_add(port_state, sock, ev);
|
||||
case EPOLL_CTL_MOD:
|
||||
return port__ctl_mod(port_state, sock, ev);
|
||||
case EPOLL_CTL_DEL:
|
||||
return port__ctl_del(port_state, sock);
|
||||
default:
|
||||
return_set_error(-1, ERROR_INVALID_PARAMETER);
|
||||
}
|
||||
}
|
||||
|
||||
int port_ctl(port_state_t* port_state,
|
||||
int op,
|
||||
SOCKET sock,
|
||||
struct epoll_event* ev) {
|
||||
int result;
|
||||
|
||||
EnterCriticalSection(&port_state->lock);
|
||||
result = port__ctl_op(port_state, op, sock, ev);
|
||||
LeaveCriticalSection(&port_state->lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int port_register_socket_handle(port_state_t* port_state,
|
||||
sock_state_t* sock_state,
|
||||
SOCKET socket) {
|
||||
if (tree_add(&port_state->sock_tree,
|
||||
sock_state_to_tree_node(sock_state),
|
||||
socket) < 0)
|
||||
return_set_error(-1, ERROR_ALREADY_EXISTS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void port_unregister_socket_handle(port_state_t* port_state,
|
||||
sock_state_t* sock_state) {
|
||||
tree_del(&port_state->sock_tree, sock_state_to_tree_node(sock_state));
|
||||
}
|
||||
|
||||
sock_state_t* port_find_socket(port_state_t* port_state, SOCKET socket) {
|
||||
tree_node_t* tree_node = tree_find(&port_state->sock_tree, socket);
|
||||
if (tree_node == NULL)
|
||||
return_set_error(NULL, ERROR_NOT_FOUND);
|
||||
return sock_state_from_tree_node(tree_node);
|
||||
}
|
||||
|
||||
void port_request_socket_update(port_state_t* port_state,
|
||||
sock_state_t* sock_state) {
|
||||
if (queue_enqueued(sock_state_to_queue_node(sock_state)))
|
||||
return;
|
||||
queue_append(&port_state->sock_update_queue,
|
||||
sock_state_to_queue_node(sock_state));
|
||||
}
|
||||
|
||||
void port_cancel_socket_update(port_state_t* port_state,
|
||||
sock_state_t* sock_state) {
|
||||
unused_var(port_state);
|
||||
if (!queue_enqueued(sock_state_to_queue_node(sock_state)))
|
||||
return;
|
||||
queue_remove(sock_state_to_queue_node(sock_state));
|
||||
}
|
||||
|
||||
void port_add_deleted_socket(port_state_t* port_state,
|
||||
sock_state_t* sock_state) {
|
||||
if (queue_enqueued(sock_state_to_queue_node(sock_state)))
|
||||
return;
|
||||
queue_append(&port_state->sock_deleted_queue,
|
||||
sock_state_to_queue_node(sock_state));
|
||||
}
|
||||
|
||||
void port_remove_deleted_socket(port_state_t* port_state,
|
||||
sock_state_t* sock_state) {
|
||||
unused_var(port_state);
|
||||
if (!queue_enqueued(sock_state_to_queue_node(sock_state)))
|
||||
return;
|
||||
queue_remove(sock_state_to_queue_node(sock_state));
|
||||
}
|
||||
|
||||
void queue_init(queue_t* queue) {
|
||||
queue_node_init(&queue->head);
|
||||
}
|
||||
|
||||
void queue_node_init(queue_node_t* node) {
|
||||
node->prev = node;
|
||||
node->next = node;
|
||||
}
|
||||
|
||||
static inline void queue__detach_node(queue_node_t* node) {
|
||||
node->prev->next = node->next;
|
||||
node->next->prev = node->prev;
|
||||
}
|
||||
|
||||
queue_node_t* queue_first(const queue_t* queue) {
|
||||
return !queue_empty(queue) ? queue->head.next : NULL;
|
||||
}
|
||||
|
||||
queue_node_t* queue_last(const queue_t* queue) {
|
||||
return !queue_empty(queue) ? queue->head.prev : NULL;
|
||||
}
|
||||
|
||||
void queue_prepend(queue_t* queue, queue_node_t* node) {
|
||||
node->next = queue->head.next;
|
||||
node->prev = &queue->head;
|
||||
node->next->prev = node;
|
||||
queue->head.next = node;
|
||||
}
|
||||
|
||||
void queue_append(queue_t* queue, queue_node_t* node) {
|
||||
node->next = &queue->head;
|
||||
node->prev = queue->head.prev;
|
||||
node->prev->next = node;
|
||||
queue->head.prev = node;
|
||||
}
|
||||
|
||||
void queue_move_first(queue_t* queue, queue_node_t* node) {
|
||||
queue__detach_node(node);
|
||||
queue_prepend(queue, node);
|
||||
}
|
||||
|
||||
void queue_move_last(queue_t* queue, queue_node_t* node) {
|
||||
queue__detach_node(node);
|
||||
queue_append(queue, node);
|
||||
}
|
||||
|
||||
void queue_remove(queue_node_t* node) {
|
||||
queue__detach_node(node);
|
||||
queue_node_init(node);
|
||||
}
|
||||
|
||||
bool queue_empty(const queue_t* queue) {
|
||||
return !queue_enqueued(&queue->head);
|
||||
}
|
||||
|
||||
bool queue_enqueued(const queue_node_t* node) {
|
||||
return node->prev != node;
|
||||
}
|
||||
|
||||
/* clang-format off */
|
||||
static const long REFLOCK__REF = (long) 0x00000001;
|
||||
static const long REFLOCK__REF_MASK = (long) 0x0fffffff;
|
||||
static const long REFLOCK__DESTROY = (long) 0x10000000;
|
||||
static const long REFLOCK__DESTROY_MASK = (long) 0xf0000000;
|
||||
static const long REFLOCK__POISON = (long) 0x300DEAD0;
|
||||
/* clang-format on */
|
||||
|
||||
static HANDLE reflock__keyed_event = NULL;
|
||||
|
||||
int reflock_global_init(void) {
|
||||
NTSTATUS status =
|
||||
NtCreateKeyedEvent(&reflock__keyed_event, ~(ACCESS_MASK) 0, NULL, 0);
|
||||
if (status != STATUS_SUCCESS)
|
||||
return_set_error(-1, RtlNtStatusToDosError(status));
|
||||
return 0;
|
||||
}
|
||||
|
||||
void reflock_init(reflock_t* reflock) {
|
||||
reflock->state = 0;
|
||||
}
|
||||
|
||||
static void reflock__signal_event(void* address) {
|
||||
NTSTATUS status =
|
||||
NtReleaseKeyedEvent(reflock__keyed_event, address, FALSE, NULL);
|
||||
if (status != STATUS_SUCCESS)
|
||||
abort();
|
||||
}
|
||||
|
||||
static void reflock__await_event(void* address) {
|
||||
NTSTATUS status =
|
||||
NtWaitForKeyedEvent(reflock__keyed_event, address, FALSE, NULL);
|
||||
if (status != STATUS_SUCCESS)
|
||||
abort();
|
||||
}
|
||||
|
||||
void reflock_ref(reflock_t* reflock) {
|
||||
long state = InterlockedAdd(&reflock->state, REFLOCK__REF);
|
||||
unused_var(state);
|
||||
assert((state & REFLOCK__DESTROY_MASK) == 0); /* Overflow or destroyed. */
|
||||
}
|
||||
|
||||
void reflock_unref(reflock_t* reflock) {
|
||||
long state = InterlockedAdd(&reflock->state, -REFLOCK__REF);
|
||||
long ref_count = state & REFLOCK__REF_MASK;
|
||||
long destroy = state & REFLOCK__DESTROY_MASK;
|
||||
|
||||
unused_var(ref_count);
|
||||
unused_var(destroy);
|
||||
|
||||
if (state == REFLOCK__DESTROY)
|
||||
reflock__signal_event(reflock);
|
||||
else
|
||||
assert(destroy == 0 || ref_count > 0);
|
||||
}
|
||||
|
||||
void reflock_unref_and_destroy(reflock_t* reflock) {
|
||||
long state =
|
||||
InterlockedAdd(&reflock->state, REFLOCK__DESTROY - REFLOCK__REF);
|
||||
long ref_count = state & REFLOCK__REF_MASK;
|
||||
|
||||
assert((state & REFLOCK__DESTROY_MASK) ==
|
||||
REFLOCK__DESTROY); /* Underflow or already destroyed. */
|
||||
|
||||
if (ref_count != 0)
|
||||
reflock__await_event(reflock);
|
||||
|
||||
state = InterlockedExchange(&reflock->state, REFLOCK__POISON);
|
||||
assert(state == REFLOCK__DESTROY);
|
||||
}
|
||||
|
||||
static const uint32_t SOCK__KNOWN_EPOLL_EVENTS =
|
||||
EPOLLIN | EPOLLPRI | EPOLLOUT | EPOLLERR | EPOLLHUP | EPOLLRDNORM |
|
||||
EPOLLRDBAND | EPOLLWRNORM | EPOLLWRBAND | EPOLLMSG | EPOLLRDHUP;
|
||||
|
||||
typedef enum sock__poll_status {
|
||||
SOCK__POLL_IDLE = 0,
|
||||
SOCK__POLL_PENDING,
|
||||
SOCK__POLL_CANCELLED
|
||||
} sock__poll_status_t;
|
||||
|
||||
typedef struct sock_state {
|
||||
OVERLAPPED overlapped;
|
||||
AFD_POLL_INFO poll_info;
|
||||
queue_node_t queue_node;
|
||||
tree_node_t tree_node;
|
||||
poll_group_t* poll_group;
|
||||
SOCKET base_socket;
|
||||
epoll_data_t user_data;
|
||||
uint32_t user_events;
|
||||
uint32_t pending_events;
|
||||
sock__poll_status_t poll_status;
|
||||
bool delete_pending;
|
||||
} sock_state_t;
|
||||
|
||||
static inline sock_state_t* sock__alloc(void) {
|
||||
sock_state_t* sock_state = malloc(sizeof *sock_state);
|
||||
if (sock_state == NULL)
|
||||
return_set_error(NULL, ERROR_NOT_ENOUGH_MEMORY);
|
||||
return sock_state;
|
||||
}
|
||||
|
||||
static inline void sock__free(sock_state_t* sock_state) {
|
||||
free(sock_state);
|
||||
}
|
||||
|
||||
static int sock__cancel_poll(sock_state_t* sock_state) {
|
||||
HANDLE afd_helper_handle =
|
||||
poll_group_get_afd_helper_handle(sock_state->poll_group);
|
||||
assert(sock_state->poll_status == SOCK__POLL_PENDING);
|
||||
|
||||
/* CancelIoEx() may fail with ERROR_NOT_FOUND if the overlapped operation has
|
||||
* already completed. This is not a problem and we proceed normally. */
|
||||
if (!HasOverlappedIoCompleted(&sock_state->overlapped) &&
|
||||
!CancelIoEx(afd_helper_handle, &sock_state->overlapped) &&
|
||||
GetLastError() != ERROR_NOT_FOUND)
|
||||
return_map_error(-1);
|
||||
|
||||
sock_state->poll_status = SOCK__POLL_CANCELLED;
|
||||
sock_state->pending_events = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
sock_state_t* sock_new(port_state_t* port_state, SOCKET socket) {
|
||||
SOCKET base_socket;
|
||||
poll_group_t* poll_group;
|
||||
sock_state_t* sock_state;
|
||||
|
||||
if (socket == 0 || socket == INVALID_SOCKET)
|
||||
return_set_error(NULL, ERROR_INVALID_HANDLE);
|
||||
|
||||
base_socket = ws_get_base_socket(socket);
|
||||
if (base_socket == INVALID_SOCKET)
|
||||
return NULL;
|
||||
|
||||
poll_group = poll_group_acquire(port_state);
|
||||
if (poll_group == NULL)
|
||||
return NULL;
|
||||
|
||||
sock_state = sock__alloc();
|
||||
if (sock_state == NULL)
|
||||
goto err1;
|
||||
|
||||
memset(sock_state, 0, sizeof *sock_state);
|
||||
|
||||
sock_state->base_socket = base_socket;
|
||||
sock_state->poll_group = poll_group;
|
||||
|
||||
tree_node_init(&sock_state->tree_node);
|
||||
queue_node_init(&sock_state->queue_node);
|
||||
|
||||
if (port_register_socket_handle(port_state, sock_state, socket) < 0)
|
||||
goto err2;
|
||||
|
||||
return sock_state;
|
||||
|
||||
err2:
|
||||
sock__free(sock_state);
|
||||
err1:
|
||||
poll_group_release(poll_group);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int sock__delete(port_state_t* port_state,
|
||||
sock_state_t* sock_state,
|
||||
bool force) {
|
||||
if (!sock_state->delete_pending) {
|
||||
if (sock_state->poll_status == SOCK__POLL_PENDING)
|
||||
sock__cancel_poll(sock_state);
|
||||
|
||||
port_cancel_socket_update(port_state, sock_state);
|
||||
port_unregister_socket_handle(port_state, sock_state);
|
||||
|
||||
sock_state->delete_pending = true;
|
||||
}
|
||||
|
||||
/* If the poll request still needs to complete, the sock_state object can't
|
||||
* be free()d yet. `sock_feed_event()` or `port_close()` will take care
|
||||
* of this later. */
|
||||
if (force || sock_state->poll_status == SOCK__POLL_IDLE) {
|
||||
/* Free the sock_state now. */
|
||||
port_remove_deleted_socket(port_state, sock_state);
|
||||
poll_group_release(sock_state->poll_group);
|
||||
sock__free(sock_state);
|
||||
} else {
|
||||
/* Free the socket later. */
|
||||
port_add_deleted_socket(port_state, sock_state);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sock_delete(port_state_t* port_state, sock_state_t* sock_state) {
|
||||
sock__delete(port_state, sock_state, false);
|
||||
}
|
||||
|
||||
void sock_force_delete(port_state_t* port_state, sock_state_t* sock_state) {
|
||||
sock__delete(port_state, sock_state, true);
|
||||
}
|
||||
|
||||
int sock_set_event(port_state_t* port_state,
|
||||
sock_state_t* sock_state,
|
||||
const struct epoll_event* ev) {
|
||||
/* EPOLLERR and EPOLLHUP are always reported, even when not requested by the
|
||||
* caller. However they are disabled after a event has been reported for a
|
||||
* socket for which the EPOLLONESHOT flag as set. */
|
||||
uint32_t events = ev->events | EPOLLERR | EPOLLHUP;
|
||||
|
||||
sock_state->user_events = events;
|
||||
sock_state->user_data = ev->data;
|
||||
|
||||
if ((events & SOCK__KNOWN_EPOLL_EVENTS & ~sock_state->pending_events) != 0)
|
||||
port_request_socket_update(port_state, sock_state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline DWORD sock__epoll_events_to_afd_events(uint32_t epoll_events) {
|
||||
/* Always monitor for AFD_POLL_LOCAL_CLOSE, which is triggered when the
|
||||
* socket is closed with closesocket() or CloseHandle(). */
|
||||
DWORD afd_events = AFD_POLL_LOCAL_CLOSE;
|
||||
|
||||
if (epoll_events & (EPOLLIN | EPOLLRDNORM))
|
||||
afd_events |= AFD_POLL_RECEIVE | AFD_POLL_ACCEPT;
|
||||
if (epoll_events & (EPOLLPRI | EPOLLRDBAND))
|
||||
afd_events |= AFD_POLL_RECEIVE_EXPEDITED;
|
||||
if (epoll_events & (EPOLLOUT | EPOLLWRNORM | EPOLLWRBAND))
|
||||
afd_events |= AFD_POLL_SEND;
|
||||
if (epoll_events & (EPOLLIN | EPOLLRDNORM | EPOLLRDHUP))
|
||||
afd_events |= AFD_POLL_DISCONNECT;
|
||||
if (epoll_events & EPOLLHUP)
|
||||
afd_events |= AFD_POLL_ABORT;
|
||||
if (epoll_events & EPOLLERR)
|
||||
afd_events |= AFD_POLL_CONNECT_FAIL;
|
||||
|
||||
return afd_events;
|
||||
}
|
||||
|
||||
static inline uint32_t sock__afd_events_to_epoll_events(DWORD afd_events) {
|
||||
uint32_t epoll_events = 0;
|
||||
|
||||
if (afd_events & (AFD_POLL_RECEIVE | AFD_POLL_ACCEPT))
|
||||
epoll_events |= EPOLLIN | EPOLLRDNORM;
|
||||
if (afd_events & AFD_POLL_RECEIVE_EXPEDITED)
|
||||
epoll_events |= EPOLLPRI | EPOLLRDBAND;
|
||||
if (afd_events & AFD_POLL_SEND)
|
||||
epoll_events |= EPOLLOUT | EPOLLWRNORM | EPOLLWRBAND;
|
||||
if (afd_events & AFD_POLL_DISCONNECT)
|
||||
epoll_events |= EPOLLIN | EPOLLRDNORM | EPOLLRDHUP;
|
||||
if (afd_events & AFD_POLL_ABORT)
|
||||
epoll_events |= EPOLLHUP;
|
||||
if (afd_events & AFD_POLL_CONNECT_FAIL)
|
||||
/* Linux reports all these events after connect() has failed. */
|
||||
epoll_events |=
|
||||
EPOLLIN | EPOLLOUT | EPOLLERR | EPOLLRDNORM | EPOLLWRNORM | EPOLLRDHUP;
|
||||
|
||||
return epoll_events;
|
||||
}
|
||||
|
||||
int sock_update(port_state_t* port_state, sock_state_t* sock_state) {
|
||||
assert(!sock_state->delete_pending);
|
||||
|
||||
if ((sock_state->poll_status == SOCK__POLL_PENDING) &&
|
||||
(sock_state->user_events & SOCK__KNOWN_EPOLL_EVENTS &
|
||||
~sock_state->pending_events) == 0) {
|
||||
/* All the events the user is interested in are already being monitored by
|
||||
* the pending poll operation. It might spuriously complete because of an
|
||||
* event that we're no longer interested in; when that happens we'll submit
|
||||
* a new poll operation with the updated event mask. */
|
||||
|
||||
} else if (sock_state->poll_status == SOCK__POLL_PENDING) {
|
||||
/* A poll operation is already pending, but it's not monitoring for all the
|
||||
* events that the user is interested in. Therefore, cancel the pending
|
||||
* poll operation; when we receive it's completion package, a new poll
|
||||
* operation will be submitted with the correct event mask. */
|
||||
if (sock__cancel_poll(sock_state) < 0)
|
||||
return -1;
|
||||
|
||||
} else if (sock_state->poll_status == SOCK__POLL_CANCELLED) {
|
||||
/* The poll operation has already been cancelled, we're still waiting for
|
||||
* it to return. For now, there's nothing that needs to be done. */
|
||||
|
||||
} else if (sock_state->poll_status == SOCK__POLL_IDLE) {
|
||||
/* No poll operation is pending; start one. */
|
||||
sock_state->poll_info.Exclusive = FALSE;
|
||||
sock_state->poll_info.NumberOfHandles = 1;
|
||||
sock_state->poll_info.Timeout.QuadPart = INT64_MAX;
|
||||
sock_state->poll_info.Handles[0].Handle = (HANDLE) sock_state->base_socket;
|
||||
sock_state->poll_info.Handles[0].Status = 0;
|
||||
sock_state->poll_info.Handles[0].Events =
|
||||
sock__epoll_events_to_afd_events(sock_state->user_events);
|
||||
|
||||
memset(&sock_state->overlapped, 0, sizeof sock_state->overlapped);
|
||||
|
||||
if (afd_poll(poll_group_get_afd_helper_handle(sock_state->poll_group),
|
||||
&sock_state->poll_info,
|
||||
&sock_state->overlapped) < 0) {
|
||||
switch (GetLastError()) {
|
||||
case ERROR_IO_PENDING:
|
||||
/* Overlapped poll operation in progress; this is expected. */
|
||||
break;
|
||||
case ERROR_INVALID_HANDLE:
|
||||
/* Socket closed; it'll be dropped from the epoll set. */
|
||||
return sock__delete(port_state, sock_state, false);
|
||||
default:
|
||||
/* Other errors are propagated to the caller. */
|
||||
return_map_error(-1);
|
||||
}
|
||||
}
|
||||
|
||||
/* The poll request was successfully submitted. */
|
||||
sock_state->poll_status = SOCK__POLL_PENDING;
|
||||
sock_state->pending_events = sock_state->user_events;
|
||||
|
||||
} else {
|
||||
/* Unreachable. */
|
||||
assert(false);
|
||||
}
|
||||
|
||||
port_cancel_socket_update(port_state, sock_state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sock_feed_event(port_state_t* port_state,
|
||||
OVERLAPPED* overlapped,
|
||||
struct epoll_event* ev) {
|
||||
sock_state_t* sock_state =
|
||||
container_of(overlapped, sock_state_t, overlapped);
|
||||
AFD_POLL_INFO* poll_info = &sock_state->poll_info;
|
||||
uint32_t epoll_events = 0;
|
||||
|
||||
sock_state->poll_status = SOCK__POLL_IDLE;
|
||||
sock_state->pending_events = 0;
|
||||
|
||||
if (sock_state->delete_pending) {
|
||||
/* Socket has been deleted earlier and can now be freed. */
|
||||
return sock__delete(port_state, sock_state, false);
|
||||
|
||||
} else if ((NTSTATUS) overlapped->Internal == STATUS_CANCELLED) {
|
||||
/* The poll request was cancelled by CancelIoEx. */
|
||||
|
||||
} else if (!NT_SUCCESS(overlapped->Internal)) {
|
||||
/* The overlapped request itself failed in an unexpected way. */
|
||||
epoll_events = EPOLLERR;
|
||||
|
||||
} else if (poll_info->NumberOfHandles < 1) {
|
||||
/* This poll operation succeeded but didn't report any socket events. */
|
||||
|
||||
} else if (poll_info->Handles[0].Events & AFD_POLL_LOCAL_CLOSE) {
|
||||
/* The poll operation reported that the socket was closed. */
|
||||
return sock__delete(port_state, sock_state, false);
|
||||
|
||||
} else {
|
||||
/* Events related to our socket were reported. */
|
||||
epoll_events =
|
||||
sock__afd_events_to_epoll_events(poll_info->Handles[0].Events);
|
||||
}
|
||||
|
||||
/* Requeue the socket so a new poll request will be submitted. */
|
||||
port_request_socket_update(port_state, sock_state);
|
||||
|
||||
/* Filter out events that the user didn't ask for. */
|
||||
epoll_events &= sock_state->user_events;
|
||||
|
||||
/* Return if there are no epoll events to report. */
|
||||
if (epoll_events == 0)
|
||||
return 0;
|
||||
|
||||
/* If the the socket has the EPOLLONESHOT flag set, unmonitor all events,
|
||||
* even EPOLLERR and EPOLLHUP. But always keep looking for closed sockets. */
|
||||
if (sock_state->user_events & EPOLLONESHOT)
|
||||
sock_state->user_events = 0;
|
||||
|
||||
ev->data = sock_state->user_data;
|
||||
ev->events = epoll_events;
|
||||
return 1;
|
||||
}
|
||||
|
||||
queue_node_t* sock_state_to_queue_node(sock_state_t* sock_state) {
|
||||
return &sock_state->queue_node;
|
||||
}
|
||||
|
||||
sock_state_t* sock_state_from_tree_node(tree_node_t* tree_node) {
|
||||
return container_of(tree_node, sock_state_t, tree_node);
|
||||
}
|
||||
|
||||
tree_node_t* sock_state_to_tree_node(sock_state_t* sock_state) {
|
||||
return &sock_state->tree_node;
|
||||
}
|
||||
|
||||
sock_state_t* sock_state_from_queue_node(queue_node_t* queue_node) {
|
||||
return container_of(queue_node, sock_state_t, queue_node);
|
||||
}
|
||||
|
||||
void ts_tree_init(ts_tree_t* ts_tree) {
|
||||
tree_init(&ts_tree->tree);
|
||||
InitializeSRWLock(&ts_tree->lock);
|
||||
}
|
||||
|
||||
void ts_tree_node_init(ts_tree_node_t* node) {
|
||||
tree_node_init(&node->tree_node);
|
||||
reflock_init(&node->reflock);
|
||||
}
|
||||
|
||||
int ts_tree_add(ts_tree_t* ts_tree, ts_tree_node_t* node, uintptr_t key) {
|
||||
int r;
|
||||
|
||||
AcquireSRWLockExclusive(&ts_tree->lock);
|
||||
r = tree_add(&ts_tree->tree, &node->tree_node, key);
|
||||
ReleaseSRWLockExclusive(&ts_tree->lock);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline ts_tree_node_t* ts_tree__find_node(ts_tree_t* ts_tree,
|
||||
uintptr_t key) {
|
||||
tree_node_t* tree_node = tree_find(&ts_tree->tree, key);
|
||||
if (tree_node == NULL)
|
||||
return NULL;
|
||||
|
||||
return container_of(tree_node, ts_tree_node_t, tree_node);
|
||||
}
|
||||
|
||||
ts_tree_node_t* ts_tree_del_and_ref(ts_tree_t* ts_tree, uintptr_t key) {
|
||||
ts_tree_node_t* ts_tree_node;
|
||||
|
||||
AcquireSRWLockExclusive(&ts_tree->lock);
|
||||
|
||||
ts_tree_node = ts_tree__find_node(ts_tree, key);
|
||||
if (ts_tree_node != NULL) {
|
||||
tree_del(&ts_tree->tree, &ts_tree_node->tree_node);
|
||||
reflock_ref(&ts_tree_node->reflock);
|
||||
}
|
||||
|
||||
ReleaseSRWLockExclusive(&ts_tree->lock);
|
||||
|
||||
return ts_tree_node;
|
||||
}
|
||||
|
||||
ts_tree_node_t* ts_tree_find_and_ref(ts_tree_t* ts_tree, uintptr_t key) {
|
||||
ts_tree_node_t* ts_tree_node;
|
||||
|
||||
AcquireSRWLockShared(&ts_tree->lock);
|
||||
|
||||
ts_tree_node = ts_tree__find_node(ts_tree, key);
|
||||
if (ts_tree_node != NULL)
|
||||
reflock_ref(&ts_tree_node->reflock);
|
||||
|
||||
ReleaseSRWLockShared(&ts_tree->lock);
|
||||
|
||||
return ts_tree_node;
|
||||
}
|
||||
|
||||
void ts_tree_node_unref(ts_tree_node_t* node) {
|
||||
reflock_unref(&node->reflock);
|
||||
}
|
||||
|
||||
void ts_tree_node_unref_and_destroy(ts_tree_node_t* node) {
|
||||
reflock_unref_and_destroy(&node->reflock);
|
||||
}
|
||||
|
||||
void tree_init(tree_t* tree) {
|
||||
memset(tree, 0, sizeof *tree);
|
||||
}
|
||||
|
||||
void tree_node_init(tree_node_t* node) {
|
||||
memset(node, 0, sizeof *node);
|
||||
}
|
||||
|
||||
#define TREE__ROTATE(cis, trans) \
|
||||
tree_node_t* p = node; \
|
||||
tree_node_t* q = node->trans; \
|
||||
tree_node_t* parent = p->parent; \
|
||||
\
|
||||
if (parent) { \
|
||||
if (parent->left == p) \
|
||||
parent->left = q; \
|
||||
else \
|
||||
parent->right = q; \
|
||||
} else { \
|
||||
tree->root = q; \
|
||||
} \
|
||||
\
|
||||
q->parent = parent; \
|
||||
p->parent = q; \
|
||||
p->trans = q->cis; \
|
||||
if (p->trans) \
|
||||
p->trans->parent = p; \
|
||||
q->cis = p;
|
||||
|
||||
static inline void tree__rotate_left(tree_t* tree, tree_node_t* node) {
|
||||
TREE__ROTATE(left, right)
|
||||
}
|
||||
|
||||
static inline void tree__rotate_right(tree_t* tree, tree_node_t* node) {
|
||||
TREE__ROTATE(right, left)
|
||||
}
|
||||
|
||||
#define TREE__INSERT_OR_DESCEND(side) \
|
||||
if (parent->side) { \
|
||||
parent = parent->side; \
|
||||
} else { \
|
||||
parent->side = node; \
|
||||
break; \
|
||||
}
|
||||
|
||||
#define TREE__FIXUP_AFTER_INSERT(cis, trans) \
|
||||
tree_node_t* grandparent = parent->parent; \
|
||||
tree_node_t* uncle = grandparent->trans; \
|
||||
\
|
||||
if (uncle && uncle->red) { \
|
||||
parent->red = uncle->red = false; \
|
||||
grandparent->red = true; \
|
||||
node = grandparent; \
|
||||
} else { \
|
||||
if (node == parent->trans) { \
|
||||
tree__rotate_##cis(tree, parent); \
|
||||
node = parent; \
|
||||
parent = node->parent; \
|
||||
} \
|
||||
parent->red = false; \
|
||||
grandparent->red = true; \
|
||||
tree__rotate_##trans(tree, grandparent); \
|
||||
}
|
||||
|
||||
int tree_add(tree_t* tree, tree_node_t* node, uintptr_t key) {
|
||||
tree_node_t* parent;
|
||||
|
||||
parent = tree->root;
|
||||
if (parent) {
|
||||
for (;;) {
|
||||
if (key < parent->key) {
|
||||
TREE__INSERT_OR_DESCEND(left)
|
||||
} else if (key > parent->key) {
|
||||
TREE__INSERT_OR_DESCEND(right)
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tree->root = node;
|
||||
}
|
||||
|
||||
node->key = key;
|
||||
node->left = node->right = NULL;
|
||||
node->parent = parent;
|
||||
node->red = true;
|
||||
|
||||
for (; parent && parent->red; parent = node->parent) {
|
||||
if (parent == parent->parent->left) {
|
||||
TREE__FIXUP_AFTER_INSERT(left, right)
|
||||
} else {
|
||||
TREE__FIXUP_AFTER_INSERT(right, left)
|
||||
}
|
||||
}
|
||||
tree->root->red = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TREE__FIXUP_AFTER_REMOVE(cis, trans) \
|
||||
tree_node_t* sibling = parent->trans; \
|
||||
\
|
||||
if (sibling->red) { \
|
||||
sibling->red = false; \
|
||||
parent->red = true; \
|
||||
tree__rotate_##cis(tree, parent); \
|
||||
sibling = parent->trans; \
|
||||
} \
|
||||
if ((sibling->left && sibling->left->red) || \
|
||||
(sibling->right && sibling->right->red)) { \
|
||||
if (!sibling->trans || !sibling->trans->red) { \
|
||||
sibling->cis->red = false; \
|
||||
sibling->red = true; \
|
||||
tree__rotate_##trans(tree, sibling); \
|
||||
sibling = parent->trans; \
|
||||
} \
|
||||
sibling->red = parent->red; \
|
||||
parent->red = sibling->trans->red = false; \
|
||||
tree__rotate_##cis(tree, parent); \
|
||||
node = tree->root; \
|
||||
break; \
|
||||
} \
|
||||
sibling->red = true;
|
||||
|
||||
void tree_del(tree_t* tree, tree_node_t* node) {
|
||||
tree_node_t* parent = node->parent;
|
||||
tree_node_t* left = node->left;
|
||||
tree_node_t* right = node->right;
|
||||
tree_node_t* next;
|
||||
bool red;
|
||||
|
||||
if (!left) {
|
||||
next = right;
|
||||
} else if (!right) {
|
||||
next = left;
|
||||
} else {
|
||||
next = right;
|
||||
while (next->left)
|
||||
next = next->left;
|
||||
}
|
||||
|
||||
if (parent) {
|
||||
if (parent->left == node)
|
||||
parent->left = next;
|
||||
else
|
||||
parent->right = next;
|
||||
} else {
|
||||
tree->root = next;
|
||||
}
|
||||
|
||||
if (left && right) {
|
||||
red = next->red;
|
||||
next->red = node->red;
|
||||
next->left = left;
|
||||
left->parent = next;
|
||||
if (next != right) {
|
||||
parent = next->parent;
|
||||
next->parent = node->parent;
|
||||
node = next->right;
|
||||
parent->left = node;
|
||||
next->right = right;
|
||||
right->parent = next;
|
||||
} else {
|
||||
next->parent = parent;
|
||||
parent = next;
|
||||
node = next->right;
|
||||
}
|
||||
} else {
|
||||
red = node->red;
|
||||
node = next;
|
||||
}
|
||||
|
||||
if (node)
|
||||
node->parent = parent;
|
||||
if (red)
|
||||
return;
|
||||
if (node && node->red) {
|
||||
node->red = false;
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
if (node == tree->root)
|
||||
break;
|
||||
if (node == parent->left) {
|
||||
TREE__FIXUP_AFTER_REMOVE(left, right)
|
||||
} else {
|
||||
TREE__FIXUP_AFTER_REMOVE(right, left)
|
||||
}
|
||||
node = parent;
|
||||
parent = parent->parent;
|
||||
} while (!node->red);
|
||||
|
||||
if (node)
|
||||
node->red = false;
|
||||
}
|
||||
|
||||
tree_node_t* tree_find(const tree_t* tree, uintptr_t key) {
|
||||
tree_node_t* node = tree->root;
|
||||
while (node) {
|
||||
if (key < node->key)
|
||||
node = node->left;
|
||||
else if (key > node->key)
|
||||
node = node->right;
|
||||
else
|
||||
return node;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tree_node_t* tree_root(const tree_t* tree) {
|
||||
return tree->root;
|
||||
}
|
||||
|
||||
#ifndef SIO_BASE_HANDLE
|
||||
#define SIO_BASE_HANDLE 0x48000022
|
||||
#endif
|
||||
|
||||
int ws_global_init(void) {
|
||||
int r;
|
||||
WSADATA wsa_data;
|
||||
|
||||
r = WSAStartup(MAKEWORD(2, 2), &wsa_data);
|
||||
if (r != 0)
|
||||
return_set_error(-1, (DWORD) r);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SOCKET ws_get_base_socket(SOCKET socket) {
|
||||
SOCKET base_socket;
|
||||
DWORD bytes;
|
||||
|
||||
if (WSAIoctl(socket,
|
||||
SIO_BASE_HANDLE,
|
||||
NULL,
|
||||
0,
|
||||
&base_socket,
|
||||
sizeof base_socket,
|
||||
&bytes,
|
||||
NULL,
|
||||
NULL) == SOCKET_ERROR)
|
||||
return_map_error(INVALID_SOCKET);
|
||||
|
||||
return base_socket;
|
||||
}
|
||||
117
3rd/libzmq/external/wepoll/wepoll.h
vendored
Normal file
117
3rd/libzmq/external/wepoll/wepoll.h
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* wepoll - epoll for Windows
|
||||
* https://github.com/piscisaureus/wepoll
|
||||
*
|
||||
* Copyright 2012-2018, Bert Belder <bertbelder@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef WEPOLL_H_
|
||||
#define WEPOLL_H_
|
||||
|
||||
#ifndef WEPOLL_EXPORT
|
||||
#define WEPOLL_EXPORT
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
enum EPOLL_EVENTS {
|
||||
EPOLLIN = (int) (1U << 0),
|
||||
EPOLLPRI = (int) (1U << 1),
|
||||
EPOLLOUT = (int) (1U << 2),
|
||||
EPOLLERR = (int) (1U << 3),
|
||||
EPOLLHUP = (int) (1U << 4),
|
||||
EPOLLRDNORM = (int) (1U << 6),
|
||||
EPOLLRDBAND = (int) (1U << 7),
|
||||
EPOLLWRNORM = (int) (1U << 8),
|
||||
EPOLLWRBAND = (int) (1U << 9),
|
||||
EPOLLMSG = (int) (1U << 10), /* Never reported. */
|
||||
EPOLLRDHUP = (int) (1U << 13),
|
||||
EPOLLONESHOT = (int) (1U << 31)
|
||||
};
|
||||
|
||||
#define EPOLLIN (1U << 0)
|
||||
#define EPOLLPRI (1U << 1)
|
||||
#define EPOLLOUT (1U << 2)
|
||||
#define EPOLLERR (1U << 3)
|
||||
#define EPOLLHUP (1U << 4)
|
||||
#define EPOLLRDNORM (1U << 6)
|
||||
#define EPOLLRDBAND (1U << 7)
|
||||
#define EPOLLWRNORM (1U << 8)
|
||||
#define EPOLLWRBAND (1U << 9)
|
||||
#define EPOLLMSG (1U << 10)
|
||||
#define EPOLLRDHUP (1U << 13)
|
||||
#define EPOLLONESHOT (1U << 31)
|
||||
|
||||
#define EPOLL_CTL_ADD 1
|
||||
#define EPOLL_CTL_MOD 2
|
||||
#define EPOLL_CTL_DEL 3
|
||||
|
||||
/* clang-format on */
|
||||
|
||||
typedef void* HANDLE;
|
||||
typedef uintptr_t SOCKET;
|
||||
|
||||
typedef union epoll_data {
|
||||
void* ptr;
|
||||
int fd;
|
||||
uint32_t u32;
|
||||
uint64_t u64;
|
||||
SOCKET sock; /* Windows specific */
|
||||
HANDLE hnd; /* Windows specific */
|
||||
} epoll_data_t;
|
||||
|
||||
struct epoll_event {
|
||||
uint32_t events; /* Epoll events and flags */
|
||||
epoll_data_t data; /* User data variable */
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
WEPOLL_EXPORT HANDLE epoll_create(int size);
|
||||
WEPOLL_EXPORT HANDLE epoll_create1(int flags);
|
||||
|
||||
WEPOLL_EXPORT int epoll_close(HANDLE ephnd);
|
||||
|
||||
WEPOLL_EXPORT int epoll_ctl(HANDLE ephnd,
|
||||
int op,
|
||||
SOCKET sock,
|
||||
struct epoll_event* event);
|
||||
|
||||
WEPOLL_EXPORT int epoll_wait(HANDLE ephnd,
|
||||
struct epoll_event* events,
|
||||
int maxevents,
|
||||
int timeout);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* WEPOLL_H_ */
|
||||
788
3rd/libzmq/include/zmq.h
Normal file
788
3rd/libzmq/include/zmq.h
Normal file
@@ -0,0 +1,788 @@
|
||||
/*
|
||||
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*************************************************************************
|
||||
NOTE to contributors. This file comprises the principal public contract
|
||||
for ZeroMQ API users. Any change to this file supplied in a stable
|
||||
release SHOULD not break existing applications.
|
||||
In practice this means that the value of constants must not change, and
|
||||
that old values may not be reused for new constants.
|
||||
*************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef __ZMQ_H_INCLUDED__
|
||||
#define __ZMQ_H_INCLUDED__
|
||||
|
||||
/* Version macros for compile-time API version detection */
|
||||
#define ZMQ_VERSION_MAJOR 4
|
||||
#define ZMQ_VERSION_MINOR 3
|
||||
#define ZMQ_VERSION_PATCH 4
|
||||
|
||||
#define ZMQ_MAKE_VERSION(major, minor, patch) \
|
||||
((major) *10000 + (minor) *100 + (patch))
|
||||
#define ZMQ_VERSION \
|
||||
ZMQ_MAKE_VERSION (ZMQ_VERSION_MAJOR, ZMQ_VERSION_MINOR, ZMQ_VERSION_PATCH)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if !defined _WIN32_WCE
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#if defined _WIN32
|
||||
// Set target version to Windows Server 2008, Windows Vista or higher.
|
||||
// Windows XP (0x0501) is supported but without client & server socket types.
|
||||
#ifndef _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x0600
|
||||
#endif
|
||||
|
||||
#ifdef __MINGW32__
|
||||
// Require Windows XP or higher with MinGW for getaddrinfo().
|
||||
#if (_WIN32_WINNT >= 0x0501)
|
||||
#else
|
||||
#error You need at least Windows XP target
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Handle DSO symbol visibility */
|
||||
#if defined _WIN32
|
||||
#if defined ZMQ_STATIC
|
||||
#define ZMQ_EXPORT
|
||||
#elif defined DLL_EXPORT
|
||||
#define ZMQ_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define ZMQ_EXPORT __declspec(dllimport)
|
||||
#endif
|
||||
#else
|
||||
#if defined __SUNPRO_C || defined __SUNPRO_CC
|
||||
#define ZMQ_EXPORT __global
|
||||
#elif (defined __GNUC__ && __GNUC__ >= 4) || defined __INTEL_COMPILER
|
||||
#define ZMQ_EXPORT __attribute__ ((visibility ("default")))
|
||||
#else
|
||||
#define ZMQ_EXPORT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Define integer types needed for event interface */
|
||||
#define ZMQ_DEFINED_STDINT 1
|
||||
#if defined ZMQ_HAVE_SOLARIS || defined ZMQ_HAVE_OPENVMS
|
||||
#include <inttypes.h>
|
||||
#elif defined _MSC_VER && _MSC_VER < 1600
|
||||
#ifndef uint64_t
|
||||
typedef unsigned __int64 uint64_t;
|
||||
#endif
|
||||
#ifndef int32_t
|
||||
typedef __int32 int32_t;
|
||||
#endif
|
||||
#ifndef uint32_t
|
||||
typedef unsigned __int32 uint32_t;
|
||||
#endif
|
||||
#ifndef uint16_t
|
||||
typedef unsigned __int16 uint16_t;
|
||||
#endif
|
||||
#ifndef uint8_t
|
||||
typedef unsigned __int8 uint8_t;
|
||||
#endif
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
// 32-bit AIX's pollfd struct members are called reqevents and rtnevents so it
|
||||
// defines compatibility macros for them. Need to include that header first to
|
||||
// stop build failures since zmq_pollset_t defines them as events and revents.
|
||||
#ifdef ZMQ_HAVE_AIX
|
||||
#include <poll.h>
|
||||
#endif
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* 0MQ errors. */
|
||||
/******************************************************************************/
|
||||
|
||||
/* A number random enough not to collide with different errno ranges on */
|
||||
/* different OSes. The assumption is that error_t is at least 32-bit type. */
|
||||
#define ZMQ_HAUSNUMERO 156384712
|
||||
|
||||
/* On Windows platform some of the standard POSIX errnos are not defined. */
|
||||
#ifndef ENOTSUP
|
||||
#define ENOTSUP (ZMQ_HAUSNUMERO + 1)
|
||||
#endif
|
||||
#ifndef EPROTONOSUPPORT
|
||||
#define EPROTONOSUPPORT (ZMQ_HAUSNUMERO + 2)
|
||||
#endif
|
||||
#ifndef ENOBUFS
|
||||
#define ENOBUFS (ZMQ_HAUSNUMERO + 3)
|
||||
#endif
|
||||
#ifndef ENETDOWN
|
||||
#define ENETDOWN (ZMQ_HAUSNUMERO + 4)
|
||||
#endif
|
||||
#ifndef EADDRINUSE
|
||||
#define EADDRINUSE (ZMQ_HAUSNUMERO + 5)
|
||||
#endif
|
||||
#ifndef EADDRNOTAVAIL
|
||||
#define EADDRNOTAVAIL (ZMQ_HAUSNUMERO + 6)
|
||||
#endif
|
||||
#ifndef ECONNREFUSED
|
||||
#define ECONNREFUSED (ZMQ_HAUSNUMERO + 7)
|
||||
#endif
|
||||
#ifndef EINPROGRESS
|
||||
#define EINPROGRESS (ZMQ_HAUSNUMERO + 8)
|
||||
#endif
|
||||
#ifndef ENOTSOCK
|
||||
#define ENOTSOCK (ZMQ_HAUSNUMERO + 9)
|
||||
#endif
|
||||
#ifndef EMSGSIZE
|
||||
#define EMSGSIZE (ZMQ_HAUSNUMERO + 10)
|
||||
#endif
|
||||
#ifndef EAFNOSUPPORT
|
||||
#define EAFNOSUPPORT (ZMQ_HAUSNUMERO + 11)
|
||||
#endif
|
||||
#ifndef ENETUNREACH
|
||||
#define ENETUNREACH (ZMQ_HAUSNUMERO + 12)
|
||||
#endif
|
||||
#ifndef ECONNABORTED
|
||||
#define ECONNABORTED (ZMQ_HAUSNUMERO + 13)
|
||||
#endif
|
||||
#ifndef ECONNRESET
|
||||
#define ECONNRESET (ZMQ_HAUSNUMERO + 14)
|
||||
#endif
|
||||
#ifndef ENOTCONN
|
||||
#define ENOTCONN (ZMQ_HAUSNUMERO + 15)
|
||||
#endif
|
||||
#ifndef ETIMEDOUT
|
||||
#define ETIMEDOUT (ZMQ_HAUSNUMERO + 16)
|
||||
#endif
|
||||
#ifndef EHOSTUNREACH
|
||||
#define EHOSTUNREACH (ZMQ_HAUSNUMERO + 17)
|
||||
#endif
|
||||
#ifndef ENETRESET
|
||||
#define ENETRESET (ZMQ_HAUSNUMERO + 18)
|
||||
#endif
|
||||
|
||||
/* Native 0MQ error codes. */
|
||||
#define EFSM (ZMQ_HAUSNUMERO + 51)
|
||||
#define ENOCOMPATPROTO (ZMQ_HAUSNUMERO + 52)
|
||||
#define ETERM (ZMQ_HAUSNUMERO + 53)
|
||||
#define EMTHREAD (ZMQ_HAUSNUMERO + 54)
|
||||
|
||||
/* This function retrieves the errno as it is known to 0MQ library. The goal */
|
||||
/* of this function is to make the code 100% portable, including where 0MQ */
|
||||
/* compiled with certain CRT library (on Windows) is linked to an */
|
||||
/* application that uses different CRT library. */
|
||||
ZMQ_EXPORT int zmq_errno (void);
|
||||
|
||||
/* Resolves system errors and 0MQ errors to human-readable string. */
|
||||
ZMQ_EXPORT const char *zmq_strerror (int errnum_);
|
||||
|
||||
/* Run-time API version detection */
|
||||
ZMQ_EXPORT void zmq_version (int *major_, int *minor_, int *patch_);
|
||||
|
||||
/******************************************************************************/
|
||||
/* 0MQ infrastructure (a.k.a. context) initialisation & termination. */
|
||||
/******************************************************************************/
|
||||
|
||||
/* Context options */
|
||||
#define ZMQ_IO_THREADS 1
|
||||
#define ZMQ_MAX_SOCKETS 2
|
||||
#define ZMQ_SOCKET_LIMIT 3
|
||||
#define ZMQ_THREAD_PRIORITY 3
|
||||
#define ZMQ_THREAD_SCHED_POLICY 4
|
||||
#define ZMQ_MAX_MSGSZ 5
|
||||
#define ZMQ_MSG_T_SIZE 6
|
||||
#define ZMQ_THREAD_AFFINITY_CPU_ADD 7
|
||||
#define ZMQ_THREAD_AFFINITY_CPU_REMOVE 8
|
||||
#define ZMQ_THREAD_NAME_PREFIX 9
|
||||
|
||||
/* Default for new contexts */
|
||||
#define ZMQ_IO_THREADS_DFLT 1
|
||||
#define ZMQ_MAX_SOCKETS_DFLT 1023
|
||||
#define ZMQ_THREAD_PRIORITY_DFLT -1
|
||||
#define ZMQ_THREAD_SCHED_POLICY_DFLT -1
|
||||
|
||||
ZMQ_EXPORT void *zmq_ctx_new (void);
|
||||
ZMQ_EXPORT int zmq_ctx_term (void *context_);
|
||||
ZMQ_EXPORT int zmq_ctx_shutdown (void *context_);
|
||||
ZMQ_EXPORT int zmq_ctx_set (void *context_, int option_, int optval_);
|
||||
ZMQ_EXPORT int zmq_ctx_get (void *context_, int option_);
|
||||
|
||||
/* Old (legacy) API */
|
||||
ZMQ_EXPORT void *zmq_init (int io_threads_);
|
||||
ZMQ_EXPORT int zmq_term (void *context_);
|
||||
ZMQ_EXPORT int zmq_ctx_destroy (void *context_);
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* 0MQ message definition. */
|
||||
/******************************************************************************/
|
||||
|
||||
/* Some architectures, like sparc64 and some variants of aarch64, enforce pointer
|
||||
* alignment and raise sigbus on violations. Make sure applications allocate
|
||||
* zmq_msg_t on addresses aligned on a pointer-size boundary to avoid this issue.
|
||||
*/
|
||||
typedef struct zmq_msg_t
|
||||
{
|
||||
#if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64))
|
||||
__declspec(align (8)) unsigned char _[64];
|
||||
#elif defined(_MSC_VER) \
|
||||
&& (defined(_M_IX86) || defined(_M_ARM_ARMV7VE) || defined(_M_ARM))
|
||||
__declspec(align (4)) unsigned char _[64];
|
||||
#elif defined(__GNUC__) || defined(__INTEL_COMPILER) \
|
||||
|| (defined(__SUNPRO_C) && __SUNPRO_C >= 0x590) \
|
||||
|| (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x590)
|
||||
unsigned char _[64] __attribute__ ((aligned (sizeof (void *))));
|
||||
#else
|
||||
unsigned char _[64];
|
||||
#endif
|
||||
} zmq_msg_t;
|
||||
|
||||
typedef void(zmq_free_fn) (void *data_, void *hint_);
|
||||
|
||||
ZMQ_EXPORT int zmq_msg_init (zmq_msg_t *msg_);
|
||||
ZMQ_EXPORT int zmq_msg_init_size (zmq_msg_t *msg_, size_t size_);
|
||||
ZMQ_EXPORT int zmq_msg_init_data (
|
||||
zmq_msg_t *msg_, void *data_, size_t size_, zmq_free_fn *ffn_, void *hint_);
|
||||
ZMQ_EXPORT int zmq_msg_send (zmq_msg_t *msg_, void *s_, int flags_);
|
||||
ZMQ_EXPORT int zmq_msg_recv (zmq_msg_t *msg_, void *s_, int flags_);
|
||||
ZMQ_EXPORT int zmq_msg_close (zmq_msg_t *msg_);
|
||||
ZMQ_EXPORT int zmq_msg_move (zmq_msg_t *dest_, zmq_msg_t *src_);
|
||||
ZMQ_EXPORT int zmq_msg_copy (zmq_msg_t *dest_, zmq_msg_t *src_);
|
||||
ZMQ_EXPORT void *zmq_msg_data (zmq_msg_t *msg_);
|
||||
ZMQ_EXPORT size_t zmq_msg_size (const zmq_msg_t *msg_);
|
||||
ZMQ_EXPORT int zmq_msg_more (const zmq_msg_t *msg_);
|
||||
ZMQ_EXPORT int zmq_msg_get (const zmq_msg_t *msg_, int property_);
|
||||
ZMQ_EXPORT int zmq_msg_set (zmq_msg_t *msg_, int property_, int optval_);
|
||||
ZMQ_EXPORT const char *zmq_msg_gets (const zmq_msg_t *msg_,
|
||||
const char *property_);
|
||||
|
||||
/******************************************************************************/
|
||||
/* 0MQ socket definition. */
|
||||
/******************************************************************************/
|
||||
|
||||
/* Socket types. */
|
||||
#define ZMQ_PAIR 0
|
||||
#define ZMQ_PUB 1
|
||||
#define ZMQ_SUB 2
|
||||
#define ZMQ_REQ 3
|
||||
#define ZMQ_REP 4
|
||||
#define ZMQ_DEALER 5
|
||||
#define ZMQ_ROUTER 6
|
||||
#define ZMQ_PULL 7
|
||||
#define ZMQ_PUSH 8
|
||||
#define ZMQ_XPUB 9
|
||||
#define ZMQ_XSUB 10
|
||||
#define ZMQ_STREAM 11
|
||||
|
||||
/* Deprecated aliases */
|
||||
#define ZMQ_XREQ ZMQ_DEALER
|
||||
#define ZMQ_XREP ZMQ_ROUTER
|
||||
|
||||
/* Socket options. */
|
||||
#define ZMQ_AFFINITY 4
|
||||
#define ZMQ_ROUTING_ID 5
|
||||
#define ZMQ_SUBSCRIBE 6
|
||||
#define ZMQ_UNSUBSCRIBE 7
|
||||
#define ZMQ_RATE 8
|
||||
#define ZMQ_RECOVERY_IVL 9
|
||||
#define ZMQ_SNDBUF 11
|
||||
#define ZMQ_RCVBUF 12
|
||||
#define ZMQ_RCVMORE 13
|
||||
#define ZMQ_FD 14
|
||||
#define ZMQ_EVENTS 15
|
||||
#define ZMQ_TYPE 16
|
||||
#define ZMQ_LINGER 17
|
||||
#define ZMQ_RECONNECT_IVL 18
|
||||
#define ZMQ_BACKLOG 19
|
||||
#define ZMQ_RECONNECT_IVL_MAX 21
|
||||
#define ZMQ_MAXMSGSIZE 22
|
||||
#define ZMQ_SNDHWM 23
|
||||
#define ZMQ_RCVHWM 24
|
||||
#define ZMQ_MULTICAST_HOPS 25
|
||||
#define ZMQ_RCVTIMEO 27
|
||||
#define ZMQ_SNDTIMEO 28
|
||||
#define ZMQ_LAST_ENDPOINT 32
|
||||
#define ZMQ_ROUTER_MANDATORY 33
|
||||
#define ZMQ_TCP_KEEPALIVE 34
|
||||
#define ZMQ_TCP_KEEPALIVE_CNT 35
|
||||
#define ZMQ_TCP_KEEPALIVE_IDLE 36
|
||||
#define ZMQ_TCP_KEEPALIVE_INTVL 37
|
||||
#define ZMQ_IMMEDIATE 39
|
||||
#define ZMQ_XPUB_VERBOSE 40
|
||||
#define ZMQ_ROUTER_RAW 41
|
||||
#define ZMQ_IPV6 42
|
||||
#define ZMQ_MECHANISM 43
|
||||
#define ZMQ_PLAIN_SERVER 44
|
||||
#define ZMQ_PLAIN_USERNAME 45
|
||||
#define ZMQ_PLAIN_PASSWORD 46
|
||||
#define ZMQ_CURVE_SERVER 47
|
||||
#define ZMQ_CURVE_PUBLICKEY 48
|
||||
#define ZMQ_CURVE_SECRETKEY 49
|
||||
#define ZMQ_CURVE_SERVERKEY 50
|
||||
#define ZMQ_PROBE_ROUTER 51
|
||||
#define ZMQ_REQ_CORRELATE 52
|
||||
#define ZMQ_REQ_RELAXED 53
|
||||
#define ZMQ_CONFLATE 54
|
||||
#define ZMQ_ZAP_DOMAIN 55
|
||||
#define ZMQ_ROUTER_HANDOVER 56
|
||||
#define ZMQ_TOS 57
|
||||
#define ZMQ_CONNECT_ROUTING_ID 61
|
||||
#define ZMQ_GSSAPI_SERVER 62
|
||||
#define ZMQ_GSSAPI_PRINCIPAL 63
|
||||
#define ZMQ_GSSAPI_SERVICE_PRINCIPAL 64
|
||||
#define ZMQ_GSSAPI_PLAINTEXT 65
|
||||
#define ZMQ_HANDSHAKE_IVL 66
|
||||
#define ZMQ_SOCKS_PROXY 68
|
||||
#define ZMQ_XPUB_NODROP 69
|
||||
#define ZMQ_BLOCKY 70
|
||||
#define ZMQ_XPUB_MANUAL 71
|
||||
#define ZMQ_XPUB_WELCOME_MSG 72
|
||||
#define ZMQ_STREAM_NOTIFY 73
|
||||
#define ZMQ_INVERT_MATCHING 74
|
||||
#define ZMQ_HEARTBEAT_IVL 75
|
||||
#define ZMQ_HEARTBEAT_TTL 76
|
||||
#define ZMQ_HEARTBEAT_TIMEOUT 77
|
||||
#define ZMQ_XPUB_VERBOSER 78
|
||||
#define ZMQ_CONNECT_TIMEOUT 79
|
||||
#define ZMQ_TCP_MAXRT 80
|
||||
#define ZMQ_THREAD_SAFE 81
|
||||
#define ZMQ_MULTICAST_MAXTPDU 84
|
||||
#define ZMQ_VMCI_BUFFER_SIZE 85
|
||||
#define ZMQ_VMCI_BUFFER_MIN_SIZE 86
|
||||
#define ZMQ_VMCI_BUFFER_MAX_SIZE 87
|
||||
#define ZMQ_VMCI_CONNECT_TIMEOUT 88
|
||||
#define ZMQ_USE_FD 89
|
||||
#define ZMQ_GSSAPI_PRINCIPAL_NAMETYPE 90
|
||||
#define ZMQ_GSSAPI_SERVICE_PRINCIPAL_NAMETYPE 91
|
||||
#define ZMQ_BINDTODEVICE 92
|
||||
|
||||
/* Message options */
|
||||
#define ZMQ_MORE 1
|
||||
#define ZMQ_SHARED 3
|
||||
|
||||
/* Send/recv options. */
|
||||
#define ZMQ_DONTWAIT 1
|
||||
#define ZMQ_SNDMORE 2
|
||||
|
||||
/* Security mechanisms */
|
||||
#define ZMQ_NULL 0
|
||||
#define ZMQ_PLAIN 1
|
||||
#define ZMQ_CURVE 2
|
||||
#define ZMQ_GSSAPI 3
|
||||
|
||||
/* RADIO-DISH protocol */
|
||||
#define ZMQ_GROUP_MAX_LENGTH 255
|
||||
|
||||
/* Deprecated options and aliases */
|
||||
#define ZMQ_IDENTITY ZMQ_ROUTING_ID
|
||||
#define ZMQ_CONNECT_RID ZMQ_CONNECT_ROUTING_ID
|
||||
#define ZMQ_TCP_ACCEPT_FILTER 38
|
||||
#define ZMQ_IPC_FILTER_PID 58
|
||||
#define ZMQ_IPC_FILTER_UID 59
|
||||
#define ZMQ_IPC_FILTER_GID 60
|
||||
#define ZMQ_IPV4ONLY 31
|
||||
#define ZMQ_DELAY_ATTACH_ON_CONNECT ZMQ_IMMEDIATE
|
||||
#define ZMQ_NOBLOCK ZMQ_DONTWAIT
|
||||
#define ZMQ_FAIL_UNROUTABLE ZMQ_ROUTER_MANDATORY
|
||||
#define ZMQ_ROUTER_BEHAVIOR ZMQ_ROUTER_MANDATORY
|
||||
|
||||
/* Deprecated Message options */
|
||||
#define ZMQ_SRCFD 2
|
||||
|
||||
/******************************************************************************/
|
||||
/* GSSAPI definitions */
|
||||
/******************************************************************************/
|
||||
|
||||
/* GSSAPI principal name types */
|
||||
#define ZMQ_GSSAPI_NT_HOSTBASED 0
|
||||
#define ZMQ_GSSAPI_NT_USER_NAME 1
|
||||
#define ZMQ_GSSAPI_NT_KRB5_PRINCIPAL 2
|
||||
|
||||
/******************************************************************************/
|
||||
/* 0MQ socket events and monitoring */
|
||||
/******************************************************************************/
|
||||
|
||||
/* Socket transport events (TCP, IPC and TIPC only) */
|
||||
|
||||
#define ZMQ_EVENT_CONNECTED 0x0001
|
||||
#define ZMQ_EVENT_CONNECT_DELAYED 0x0002
|
||||
#define ZMQ_EVENT_CONNECT_RETRIED 0x0004
|
||||
#define ZMQ_EVENT_LISTENING 0x0008
|
||||
#define ZMQ_EVENT_BIND_FAILED 0x0010
|
||||
#define ZMQ_EVENT_ACCEPTED 0x0020
|
||||
#define ZMQ_EVENT_ACCEPT_FAILED 0x0040
|
||||
#define ZMQ_EVENT_CLOSED 0x0080
|
||||
#define ZMQ_EVENT_CLOSE_FAILED 0x0100
|
||||
#define ZMQ_EVENT_DISCONNECTED 0x0200
|
||||
#define ZMQ_EVENT_MONITOR_STOPPED 0x0400
|
||||
#define ZMQ_EVENT_ALL 0xFFFF
|
||||
/* Unspecified system errors during handshake. Event value is an errno. */
|
||||
#define ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL 0x0800
|
||||
/* Handshake complete successfully with successful authentication (if *
|
||||
* enabled). Event value is unused. */
|
||||
#define ZMQ_EVENT_HANDSHAKE_SUCCEEDED 0x1000
|
||||
/* Protocol errors between ZMTP peers or between server and ZAP handler. *
|
||||
* Event value is one of ZMQ_PROTOCOL_ERROR_* */
|
||||
#define ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL 0x2000
|
||||
/* Failed authentication requests. Event value is the numeric ZAP status *
|
||||
* code, i.e. 300, 400 or 500. */
|
||||
#define ZMQ_EVENT_HANDSHAKE_FAILED_AUTH 0x4000
|
||||
#define ZMQ_PROTOCOL_ERROR_ZMTP_UNSPECIFIED 0x10000000
|
||||
#define ZMQ_PROTOCOL_ERROR_ZMTP_UNEXPECTED_COMMAND 0x10000001
|
||||
#define ZMQ_PROTOCOL_ERROR_ZMTP_INVALID_SEQUENCE 0x10000002
|
||||
#define ZMQ_PROTOCOL_ERROR_ZMTP_KEY_EXCHANGE 0x10000003
|
||||
#define ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_UNSPECIFIED 0x10000011
|
||||
#define ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_MESSAGE 0x10000012
|
||||
#define ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_HELLO 0x10000013
|
||||
#define ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_INITIATE 0x10000014
|
||||
#define ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_ERROR 0x10000015
|
||||
#define ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_READY 0x10000016
|
||||
#define ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_WELCOME 0x10000017
|
||||
#define ZMQ_PROTOCOL_ERROR_ZMTP_INVALID_METADATA 0x10000018
|
||||
// the following two may be due to erroneous configuration of a peer
|
||||
#define ZMQ_PROTOCOL_ERROR_ZMTP_CRYPTOGRAPHIC 0x11000001
|
||||
#define ZMQ_PROTOCOL_ERROR_ZMTP_MECHANISM_MISMATCH 0x11000002
|
||||
#define ZMQ_PROTOCOL_ERROR_ZAP_UNSPECIFIED 0x20000000
|
||||
#define ZMQ_PROTOCOL_ERROR_ZAP_MALFORMED_REPLY 0x20000001
|
||||
#define ZMQ_PROTOCOL_ERROR_ZAP_BAD_REQUEST_ID 0x20000002
|
||||
#define ZMQ_PROTOCOL_ERROR_ZAP_BAD_VERSION 0x20000003
|
||||
#define ZMQ_PROTOCOL_ERROR_ZAP_INVALID_STATUS_CODE 0x20000004
|
||||
#define ZMQ_PROTOCOL_ERROR_ZAP_INVALID_METADATA 0x20000005
|
||||
#define ZMQ_PROTOCOL_ERROR_WS_UNSPECIFIED 0x30000000
|
||||
|
||||
ZMQ_EXPORT void *zmq_socket (void *, int type_);
|
||||
ZMQ_EXPORT int zmq_close (void *s_);
|
||||
ZMQ_EXPORT int
|
||||
zmq_setsockopt (void *s_, int option_, const void *optval_, size_t optvallen_);
|
||||
ZMQ_EXPORT int
|
||||
zmq_getsockopt (void *s_, int option_, void *optval_, size_t *optvallen_);
|
||||
ZMQ_EXPORT int zmq_bind (void *s_, const char *addr_);
|
||||
ZMQ_EXPORT int zmq_connect (void *s_, const char *addr_);
|
||||
ZMQ_EXPORT int zmq_unbind (void *s_, const char *addr_);
|
||||
ZMQ_EXPORT int zmq_disconnect (void *s_, const char *addr_);
|
||||
ZMQ_EXPORT int zmq_send (void *s_, const void *buf_, size_t len_, int flags_);
|
||||
ZMQ_EXPORT int
|
||||
zmq_send_const (void *s_, const void *buf_, size_t len_, int flags_);
|
||||
ZMQ_EXPORT int zmq_recv (void *s_, void *buf_, size_t len_, int flags_);
|
||||
ZMQ_EXPORT int zmq_socket_monitor (void *s_, const char *addr_, int events_);
|
||||
|
||||
/******************************************************************************/
|
||||
/* Hide socket fd type; this was before zmq_poller_event_t typedef below */
|
||||
/******************************************************************************/
|
||||
|
||||
#if defined _WIN32
|
||||
// Windows uses a pointer-sized unsigned integer to store the socket fd.
|
||||
#if defined _WIN64
|
||||
typedef unsigned __int64 zmq_fd_t;
|
||||
#else
|
||||
typedef unsigned int zmq_fd_t;
|
||||
#endif
|
||||
#else
|
||||
typedef int zmq_fd_t;
|
||||
#endif
|
||||
|
||||
/******************************************************************************/
|
||||
/* Deprecated I/O multiplexing. Prefer using zmq_poller API */
|
||||
/******************************************************************************/
|
||||
|
||||
#define ZMQ_POLLIN 1
|
||||
#define ZMQ_POLLOUT 2
|
||||
#define ZMQ_POLLERR 4
|
||||
#define ZMQ_POLLPRI 8
|
||||
|
||||
typedef struct zmq_pollitem_t
|
||||
{
|
||||
void *socket;
|
||||
zmq_fd_t fd;
|
||||
short events;
|
||||
short revents;
|
||||
} zmq_pollitem_t;
|
||||
|
||||
#define ZMQ_POLLITEMS_DFLT 16
|
||||
|
||||
ZMQ_EXPORT int zmq_poll (zmq_pollitem_t *items_, int nitems_, long timeout_);
|
||||
|
||||
/******************************************************************************/
|
||||
/* Message proxying */
|
||||
/******************************************************************************/
|
||||
|
||||
ZMQ_EXPORT int zmq_proxy (void *frontend_, void *backend_, void *capture_);
|
||||
ZMQ_EXPORT int zmq_proxy_steerable (void *frontend_,
|
||||
void *backend_,
|
||||
void *capture_,
|
||||
void *control_);
|
||||
|
||||
/******************************************************************************/
|
||||
/* Probe library capabilities */
|
||||
/******************************************************************************/
|
||||
|
||||
#define ZMQ_HAS_CAPABILITIES 1
|
||||
ZMQ_EXPORT int zmq_has (const char *capability_);
|
||||
|
||||
/* Deprecated aliases */
|
||||
#define ZMQ_STREAMER 1
|
||||
#define ZMQ_FORWARDER 2
|
||||
#define ZMQ_QUEUE 3
|
||||
|
||||
/* Deprecated methods */
|
||||
ZMQ_EXPORT int zmq_device (int type_, void *frontend_, void *backend_);
|
||||
ZMQ_EXPORT int zmq_sendmsg (void *s_, zmq_msg_t *msg_, int flags_);
|
||||
ZMQ_EXPORT int zmq_recvmsg (void *s_, zmq_msg_t *msg_, int flags_);
|
||||
struct iovec;
|
||||
ZMQ_EXPORT int
|
||||
zmq_sendiov (void *s_, struct iovec *iov_, size_t count_, int flags_);
|
||||
ZMQ_EXPORT int
|
||||
zmq_recviov (void *s_, struct iovec *iov_, size_t *count_, int flags_);
|
||||
|
||||
/******************************************************************************/
|
||||
/* Encryption functions */
|
||||
/******************************************************************************/
|
||||
|
||||
/* Encode data with Z85 encoding. Returns encoded data */
|
||||
ZMQ_EXPORT char *
|
||||
zmq_z85_encode (char *dest_, const uint8_t *data_, size_t size_);
|
||||
|
||||
/* Decode data with Z85 encoding. Returns decoded data */
|
||||
ZMQ_EXPORT uint8_t *zmq_z85_decode (uint8_t *dest_, const char *string_);
|
||||
|
||||
/* Generate z85-encoded public and private keypair with tweetnacl/libsodium. */
|
||||
/* Returns 0 on success. */
|
||||
ZMQ_EXPORT int zmq_curve_keypair (char *z85_public_key_, char *z85_secret_key_);
|
||||
|
||||
/* Derive the z85-encoded public key from the z85-encoded secret key. */
|
||||
/* Returns 0 on success. */
|
||||
ZMQ_EXPORT int zmq_curve_public (char *z85_public_key_,
|
||||
const char *z85_secret_key_);
|
||||
|
||||
/******************************************************************************/
|
||||
/* Atomic utility methods */
|
||||
/******************************************************************************/
|
||||
|
||||
ZMQ_EXPORT void *zmq_atomic_counter_new (void);
|
||||
ZMQ_EXPORT void zmq_atomic_counter_set (void *counter_, int value_);
|
||||
ZMQ_EXPORT int zmq_atomic_counter_inc (void *counter_);
|
||||
ZMQ_EXPORT int zmq_atomic_counter_dec (void *counter_);
|
||||
ZMQ_EXPORT int zmq_atomic_counter_value (void *counter_);
|
||||
ZMQ_EXPORT void zmq_atomic_counter_destroy (void **counter_p_);
|
||||
|
||||
/******************************************************************************/
|
||||
/* Scheduling timers */
|
||||
/******************************************************************************/
|
||||
|
||||
#define ZMQ_HAVE_TIMERS
|
||||
|
||||
typedef void(zmq_timer_fn) (int timer_id, void *arg);
|
||||
|
||||
ZMQ_EXPORT void *zmq_timers_new (void);
|
||||
ZMQ_EXPORT int zmq_timers_destroy (void **timers_p);
|
||||
ZMQ_EXPORT int
|
||||
zmq_timers_add (void *timers, size_t interval, zmq_timer_fn handler, void *arg);
|
||||
ZMQ_EXPORT int zmq_timers_cancel (void *timers, int timer_id);
|
||||
ZMQ_EXPORT int
|
||||
zmq_timers_set_interval (void *timers, int timer_id, size_t interval);
|
||||
ZMQ_EXPORT int zmq_timers_reset (void *timers, int timer_id);
|
||||
ZMQ_EXPORT long zmq_timers_timeout (void *timers);
|
||||
ZMQ_EXPORT int zmq_timers_execute (void *timers);
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* These functions are not documented by man pages -- use at your own risk. */
|
||||
/* If you need these to be part of the formal ZMQ API, then (a) write a man */
|
||||
/* page, and (b) write a test case in tests. */
|
||||
/******************************************************************************/
|
||||
|
||||
/* Helper functions are used by perf tests so that they don't have to care */
|
||||
/* about minutiae of time-related functions on different OS platforms. */
|
||||
|
||||
/* Starts the stopwatch. Returns the handle to the watch. */
|
||||
ZMQ_EXPORT void *zmq_stopwatch_start (void);
|
||||
|
||||
/* Returns the number of microseconds elapsed since the stopwatch was */
|
||||
/* started, but does not stop or deallocate the stopwatch. */
|
||||
ZMQ_EXPORT unsigned long zmq_stopwatch_intermediate (void *watch_);
|
||||
|
||||
/* Stops the stopwatch. Returns the number of microseconds elapsed since */
|
||||
/* the stopwatch was started, and deallocates that watch. */
|
||||
ZMQ_EXPORT unsigned long zmq_stopwatch_stop (void *watch_);
|
||||
|
||||
/* Sleeps for specified number of seconds. */
|
||||
ZMQ_EXPORT void zmq_sleep (int seconds_);
|
||||
|
||||
typedef void(zmq_thread_fn) (void *);
|
||||
|
||||
/* Start a thread. Returns a handle to the thread. */
|
||||
ZMQ_EXPORT void *zmq_threadstart (zmq_thread_fn *func_, void *arg_);
|
||||
|
||||
/* Wait for thread to complete then free up resources. */
|
||||
ZMQ_EXPORT void zmq_threadclose (void *thread_);
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* These functions are DRAFT and disabled in stable releases, and subject to */
|
||||
/* change at ANY time until declared stable. */
|
||||
/******************************************************************************/
|
||||
|
||||
#ifdef ZMQ_BUILD_DRAFT_API
|
||||
|
||||
/* DRAFT Socket types. */
|
||||
#define ZMQ_SERVER 12
|
||||
#define ZMQ_CLIENT 13
|
||||
#define ZMQ_RADIO 14
|
||||
#define ZMQ_DISH 15
|
||||
#define ZMQ_GATHER 16
|
||||
#define ZMQ_SCATTER 17
|
||||
#define ZMQ_DGRAM 18
|
||||
#define ZMQ_PEER 19
|
||||
#define ZMQ_CHANNEL 20
|
||||
|
||||
/* DRAFT Socket options. */
|
||||
#define ZMQ_ZAP_ENFORCE_DOMAIN 93
|
||||
#define ZMQ_LOOPBACK_FASTPATH 94
|
||||
#define ZMQ_METADATA 95
|
||||
#define ZMQ_MULTICAST_LOOP 96
|
||||
#define ZMQ_ROUTER_NOTIFY 97
|
||||
#define ZMQ_XPUB_MANUAL_LAST_VALUE 98
|
||||
#define ZMQ_SOCKS_USERNAME 99
|
||||
#define ZMQ_SOCKS_PASSWORD 100
|
||||
#define ZMQ_IN_BATCH_SIZE 101
|
||||
#define ZMQ_OUT_BATCH_SIZE 102
|
||||
#define ZMQ_WSS_KEY_PEM 103
|
||||
#define ZMQ_WSS_CERT_PEM 104
|
||||
#define ZMQ_WSS_TRUST_PEM 105
|
||||
#define ZMQ_WSS_HOSTNAME 106
|
||||
#define ZMQ_WSS_TRUST_SYSTEM 107
|
||||
#define ZMQ_ONLY_FIRST_SUBSCRIBE 108
|
||||
#define ZMQ_RECONNECT_STOP 109
|
||||
#define ZMQ_HELLO_MSG 110
|
||||
#define ZMQ_DISCONNECT_MSG 111
|
||||
#define ZMQ_PRIORITY 112
|
||||
|
||||
/* DRAFT ZMQ_RECONNECT_STOP options */
|
||||
#define ZMQ_RECONNECT_STOP_CONN_REFUSED 0x1
|
||||
#define ZMQ_RECONNECT_STOP_HANDSHAKE_FAILED 0x2
|
||||
#define ZMQ_RECONNECT_STOP_AFTER_DISCONNECT 0x3
|
||||
|
||||
/* DRAFT Context options */
|
||||
#define ZMQ_ZERO_COPY_RECV 10
|
||||
|
||||
/* DRAFT Context methods. */
|
||||
ZMQ_EXPORT int zmq_ctx_set_ext (void *context_,
|
||||
int option_,
|
||||
const void *optval_,
|
||||
size_t optvallen_);
|
||||
ZMQ_EXPORT int zmq_ctx_get_ext (void *context_,
|
||||
int option_,
|
||||
void *optval_,
|
||||
size_t *optvallen_);
|
||||
|
||||
/* DRAFT Socket methods. */
|
||||
ZMQ_EXPORT int zmq_join (void *s, const char *group);
|
||||
ZMQ_EXPORT int zmq_leave (void *s, const char *group);
|
||||
ZMQ_EXPORT uint32_t zmq_connect_peer (void *s_, const char *addr_);
|
||||
|
||||
/* DRAFT Msg methods. */
|
||||
ZMQ_EXPORT int zmq_msg_set_routing_id (zmq_msg_t *msg, uint32_t routing_id);
|
||||
ZMQ_EXPORT uint32_t zmq_msg_routing_id (zmq_msg_t *msg);
|
||||
ZMQ_EXPORT int zmq_msg_set_group (zmq_msg_t *msg, const char *group);
|
||||
ZMQ_EXPORT const char *zmq_msg_group (zmq_msg_t *msg);
|
||||
ZMQ_EXPORT int
|
||||
zmq_msg_init_buffer (zmq_msg_t *msg_, const void *buf_, size_t size_);
|
||||
|
||||
/* DRAFT Msg property names. */
|
||||
#define ZMQ_MSG_PROPERTY_ROUTING_ID "Routing-Id"
|
||||
#define ZMQ_MSG_PROPERTY_SOCKET_TYPE "Socket-Type"
|
||||
#define ZMQ_MSG_PROPERTY_USER_ID "User-Id"
|
||||
#define ZMQ_MSG_PROPERTY_PEER_ADDRESS "Peer-Address"
|
||||
|
||||
/* Router notify options */
|
||||
#define ZMQ_NOTIFY_CONNECT 1
|
||||
#define ZMQ_NOTIFY_DISCONNECT 2
|
||||
|
||||
/******************************************************************************/
|
||||
/* Poller polling on sockets,fd and thread-safe sockets */
|
||||
/******************************************************************************/
|
||||
|
||||
#define ZMQ_HAVE_POLLER
|
||||
|
||||
typedef struct zmq_poller_event_t
|
||||
{
|
||||
void *socket;
|
||||
zmq_fd_t fd;
|
||||
void *user_data;
|
||||
short events;
|
||||
} zmq_poller_event_t;
|
||||
|
||||
ZMQ_EXPORT void *zmq_poller_new (void);
|
||||
ZMQ_EXPORT int zmq_poller_destroy (void **poller_p);
|
||||
ZMQ_EXPORT int zmq_poller_size (void *poller);
|
||||
ZMQ_EXPORT int
|
||||
zmq_poller_add (void *poller, void *socket, void *user_data, short events);
|
||||
ZMQ_EXPORT int zmq_poller_modify (void *poller, void *socket, short events);
|
||||
ZMQ_EXPORT int zmq_poller_remove (void *poller, void *socket);
|
||||
ZMQ_EXPORT int
|
||||
zmq_poller_wait (void *poller, zmq_poller_event_t *event, long timeout);
|
||||
ZMQ_EXPORT int zmq_poller_wait_all (void *poller,
|
||||
zmq_poller_event_t *events,
|
||||
int n_events,
|
||||
long timeout);
|
||||
ZMQ_EXPORT int zmq_poller_fd (void *poller, zmq_fd_t *fd);
|
||||
|
||||
ZMQ_EXPORT int
|
||||
zmq_poller_add_fd (void *poller, zmq_fd_t fd, void *user_data, short events);
|
||||
ZMQ_EXPORT int zmq_poller_modify_fd (void *poller, zmq_fd_t fd, short events);
|
||||
ZMQ_EXPORT int zmq_poller_remove_fd (void *poller, zmq_fd_t fd);
|
||||
|
||||
ZMQ_EXPORT int zmq_socket_get_peer_state (void *socket,
|
||||
const void *routing_id,
|
||||
size_t routing_id_size);
|
||||
|
||||
/* DRAFT Socket monitoring events */
|
||||
#define ZMQ_EVENT_PIPES_STATS 0x10000
|
||||
|
||||
#define ZMQ_CURRENT_EVENT_VERSION 1
|
||||
#define ZMQ_CURRENT_EVENT_VERSION_DRAFT 2
|
||||
|
||||
#define ZMQ_EVENT_ALL_V1 ZMQ_EVENT_ALL
|
||||
#define ZMQ_EVENT_ALL_V2 ZMQ_EVENT_ALL_V1 | ZMQ_EVENT_PIPES_STATS
|
||||
|
||||
ZMQ_EXPORT int zmq_socket_monitor_versioned (
|
||||
void *s_, const char *addr_, uint64_t events_, int event_version_, int type_);
|
||||
ZMQ_EXPORT int zmq_socket_monitor_pipes_stats (void *s);
|
||||
|
||||
#endif // ZMQ_BUILD_DRAFT_API
|
||||
|
||||
|
||||
#undef ZMQ_EXPORT
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
50
3rd/libzmq/include/zmq_utils.h
Normal file
50
3rd/libzmq/include/zmq_utils.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* This file is deprecated, and all its functionality provided by zmq.h */
|
||||
/* Note that -Wpedantic compilation requires GCC to avoid using its custom
|
||||
extensions such as #warning, hence the trick below. Also, pragmas for
|
||||
warnings or other messages are not standard, not portable, and not all
|
||||
compilers even have an equivalent concept.
|
||||
So in the worst case, this include file is treated as silently empty. */
|
||||
|
||||
#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) \
|
||||
|| defined(_MSC_VER)
|
||||
#if defined(__GNUC__) || defined(__GNUG__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic warning "-Wcpp"
|
||||
#pragma GCC diagnostic ignored "-Werror"
|
||||
#pragma GCC diagnostic ignored "-Wall"
|
||||
#endif
|
||||
#pragma message( \
|
||||
"Warning: zmq_utils.h is deprecated. All its functionality is provided by zmq.h.")
|
||||
#if defined(__GNUC__) || defined(__GNUG__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
#endif
|
||||
BIN
3rd/libzmq/installer.ico
Normal file
BIN
3rd/libzmq/installer.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.8 KiB |
143
3rd/libzmq/src/address.cpp
Normal file
143
3rd/libzmq/src/address.cpp
Normal file
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "macros.hpp"
|
||||
#include "address.hpp"
|
||||
#include "ctx.hpp"
|
||||
#include "err.hpp"
|
||||
#include "tcp_address.hpp"
|
||||
#include "udp_address.hpp"
|
||||
#include "ipc_address.hpp"
|
||||
#include "tipc_address.hpp"
|
||||
#include "ws_address.hpp"
|
||||
|
||||
#if defined ZMQ_HAVE_VMCI
|
||||
#include "vmci_address.hpp"
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
zmq::address_t::address_t (const std::string &protocol_,
|
||||
const std::string &address_,
|
||||
ctx_t *parent_) :
|
||||
protocol (protocol_),
|
||||
address (address_),
|
||||
parent (parent_)
|
||||
{
|
||||
resolved.dummy = NULL;
|
||||
}
|
||||
|
||||
zmq::address_t::~address_t ()
|
||||
{
|
||||
if (protocol == protocol_name::tcp) {
|
||||
LIBZMQ_DELETE (resolved.tcp_addr);
|
||||
} else if (protocol == protocol_name::udp) {
|
||||
LIBZMQ_DELETE (resolved.udp_addr);
|
||||
}
|
||||
#ifdef ZMQ_HAVE_WS
|
||||
else if (protocol == protocol_name::ws) {
|
||||
LIBZMQ_DELETE (resolved.ws_addr);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ZMQ_HAVE_WSS
|
||||
else if (protocol == protocol_name::wss) {
|
||||
LIBZMQ_DELETE (resolved.ws_addr);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined ZMQ_HAVE_IPC
|
||||
else if (protocol == protocol_name::ipc) {
|
||||
LIBZMQ_DELETE (resolved.ipc_addr);
|
||||
}
|
||||
#endif
|
||||
#if defined ZMQ_HAVE_TIPC
|
||||
else if (protocol == protocol_name::tipc) {
|
||||
LIBZMQ_DELETE (resolved.tipc_addr);
|
||||
}
|
||||
#endif
|
||||
#if defined ZMQ_HAVE_VMCI
|
||||
else if (protocol == protocol_name::vmci) {
|
||||
LIBZMQ_DELETE (resolved.vmci_addr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int zmq::address_t::to_string (std::string &addr_) const
|
||||
{
|
||||
if (protocol == protocol_name::tcp && resolved.tcp_addr)
|
||||
return resolved.tcp_addr->to_string (addr_);
|
||||
if (protocol == protocol_name::udp && resolved.udp_addr)
|
||||
return resolved.udp_addr->to_string (addr_);
|
||||
#ifdef ZMQ_HAVE_WS
|
||||
if (protocol == protocol_name::ws && resolved.ws_addr)
|
||||
return resolved.ws_addr->to_string (addr_);
|
||||
#endif
|
||||
#ifdef ZMQ_HAVE_WSS
|
||||
if (protocol == protocol_name::wss && resolved.ws_addr)
|
||||
return resolved.ws_addr->to_string (addr_);
|
||||
#endif
|
||||
#if defined ZMQ_HAVE_IPC
|
||||
if (protocol == protocol_name::ipc && resolved.ipc_addr)
|
||||
return resolved.ipc_addr->to_string (addr_);
|
||||
#endif
|
||||
#if defined ZMQ_HAVE_TIPC
|
||||
if (protocol == protocol_name::tipc && resolved.tipc_addr)
|
||||
return resolved.tipc_addr->to_string (addr_);
|
||||
#endif
|
||||
#if defined ZMQ_HAVE_VMCI
|
||||
if (protocol == protocol_name::vmci && resolved.vmci_addr)
|
||||
return resolved.vmci_addr->to_string (addr_);
|
||||
#endif
|
||||
|
||||
if (!protocol.empty () && !address.empty ()) {
|
||||
std::stringstream s;
|
||||
s << protocol << "://" << address;
|
||||
addr_ = s.str ();
|
||||
return 0;
|
||||
}
|
||||
addr_.clear ();
|
||||
return -1;
|
||||
}
|
||||
|
||||
zmq::zmq_socklen_t zmq::get_socket_address (fd_t fd_,
|
||||
socket_end_t socket_end_,
|
||||
sockaddr_storage *ss_)
|
||||
{
|
||||
zmq_socklen_t sl = static_cast<zmq_socklen_t> (sizeof (*ss_));
|
||||
|
||||
const int rc =
|
||||
socket_end_ == socket_end_local
|
||||
? getsockname (fd_, reinterpret_cast<struct sockaddr *> (ss_), &sl)
|
||||
: getpeername (fd_, reinterpret_cast<struct sockaddr *> (ss_), &sl);
|
||||
|
||||
return rc != 0 ? 0 : sl;
|
||||
}
|
||||
162
3rd/libzmq/src/address.hpp
Normal file
162
3rd/libzmq/src/address.hpp
Normal file
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ZMQ_ADDRESS_HPP_INCLUDED__
|
||||
#define __ZMQ_ADDRESS_HPP_INCLUDED__
|
||||
|
||||
#include "fd.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
#ifndef ZMQ_HAVE_WINDOWS
|
||||
#include <sys/socket.h>
|
||||
#else
|
||||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
|
||||
namespace zmq
|
||||
{
|
||||
class ctx_t;
|
||||
class tcp_address_t;
|
||||
class udp_address_t;
|
||||
class ws_address_t;
|
||||
#ifdef ZMQ_HAVE_WSS
|
||||
class wss_address_t;
|
||||
#endif
|
||||
#if defined ZMQ_HAVE_IPC
|
||||
class ipc_address_t;
|
||||
#endif
|
||||
#if defined ZMQ_HAVE_LINUX || defined ZMQ_HAVE_VXWORKS
|
||||
class tipc_address_t;
|
||||
#endif
|
||||
#if defined ZMQ_HAVE_VMCI
|
||||
class vmci_address_t;
|
||||
#endif
|
||||
|
||||
namespace protocol_name
|
||||
{
|
||||
static const char inproc[] = "inproc";
|
||||
static const char tcp[] = "tcp";
|
||||
static const char udp[] = "udp";
|
||||
#ifdef ZMQ_HAVE_OPENPGM
|
||||
static const char pgm[] = "pgm";
|
||||
static const char epgm[] = "epgm";
|
||||
#endif
|
||||
#ifdef ZMQ_HAVE_NORM
|
||||
static const char norm[] = "norm";
|
||||
#endif
|
||||
#ifdef ZMQ_HAVE_WS
|
||||
static const char ws[] = "ws";
|
||||
#endif
|
||||
#ifdef ZMQ_HAVE_WSS
|
||||
static const char wss[] = "wss";
|
||||
#endif
|
||||
#if defined ZMQ_HAVE_IPC
|
||||
static const char ipc[] = "ipc";
|
||||
#endif
|
||||
#if defined ZMQ_HAVE_TIPC
|
||||
static const char tipc[] = "tipc";
|
||||
#endif
|
||||
#if defined ZMQ_HAVE_VMCI
|
||||
static const char vmci[] = "vmci";
|
||||
#endif
|
||||
}
|
||||
|
||||
struct address_t
|
||||
{
|
||||
address_t (const std::string &protocol_,
|
||||
const std::string &address_,
|
||||
ctx_t *parent_);
|
||||
|
||||
~address_t ();
|
||||
|
||||
const std::string protocol;
|
||||
const std::string address;
|
||||
ctx_t *const parent;
|
||||
|
||||
// Protocol specific resolved address
|
||||
// All members must be pointers to allow for consistent initialization
|
||||
union
|
||||
{
|
||||
void *dummy;
|
||||
tcp_address_t *tcp_addr;
|
||||
udp_address_t *udp_addr;
|
||||
#ifdef ZMQ_HAVE_WS
|
||||
ws_address_t *ws_addr;
|
||||
#endif
|
||||
#ifdef ZMQ_HAVE_WSS
|
||||
wss_address_t *wss_addr;
|
||||
#endif
|
||||
#if defined ZMQ_HAVE_IPC
|
||||
ipc_address_t *ipc_addr;
|
||||
#endif
|
||||
#if defined ZMQ_HAVE_LINUX || defined ZMQ_HAVE_VXWORKS
|
||||
tipc_address_t *tipc_addr;
|
||||
#endif
|
||||
#if defined ZMQ_HAVE_VMCI
|
||||
vmci_address_t *vmci_addr;
|
||||
#endif
|
||||
} resolved;
|
||||
|
||||
int to_string (std::string &addr_) const;
|
||||
};
|
||||
|
||||
#if defined(ZMQ_HAVE_HPUX) || defined(ZMQ_HAVE_VXWORKS) \
|
||||
|| defined(ZMQ_HAVE_WINDOWS)
|
||||
typedef int zmq_socklen_t;
|
||||
#else
|
||||
typedef socklen_t zmq_socklen_t;
|
||||
#endif
|
||||
|
||||
enum socket_end_t
|
||||
{
|
||||
socket_end_local,
|
||||
socket_end_remote
|
||||
};
|
||||
|
||||
zmq_socklen_t
|
||||
get_socket_address (fd_t fd_, socket_end_t socket_end_, sockaddr_storage *ss_);
|
||||
|
||||
template <typename T>
|
||||
std::string get_socket_name (fd_t fd_, socket_end_t socket_end_)
|
||||
{
|
||||
struct sockaddr_storage ss;
|
||||
const zmq_socklen_t sl = get_socket_address (fd_, socket_end_, &ss);
|
||||
if (sl == 0) {
|
||||
return std::string ();
|
||||
}
|
||||
|
||||
const T addr (reinterpret_cast<struct sockaddr *> (&ss), sl);
|
||||
std::string address_string;
|
||||
addr.to_string (address_string);
|
||||
return address_string;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
140
3rd/libzmq/src/array.hpp
Normal file
140
3rd/libzmq/src/array.hpp
Normal file
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ZMQ_ARRAY_INCLUDED__
|
||||
#define __ZMQ_ARRAY_INCLUDED__
|
||||
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#include "macros.hpp"
|
||||
|
||||
namespace zmq
|
||||
{
|
||||
// Implementation of fast arrays with O(1) access, insertion and
|
||||
// removal. The array stores pointers rather than objects.
|
||||
// O(1) is achieved by making items inheriting from
|
||||
// array_item_t<ID> class which internally stores the position
|
||||
// in the array.
|
||||
// The ID template argument is used to differentiate among arrays
|
||||
// and thus let an object be stored in different arrays.
|
||||
|
||||
// Base class for objects stored in the array. If you want to store
|
||||
// same object in multiple arrays, each of those arrays has to have
|
||||
// different ID. The item itself has to be derived from instantiations of
|
||||
// array_item_t template for all relevant IDs.
|
||||
|
||||
template <int ID = 0> class array_item_t
|
||||
{
|
||||
public:
|
||||
array_item_t () : _array_index (-1) {}
|
||||
|
||||
// The destructor doesn't have to be virtual. It is made virtual
|
||||
// just to keep ICC and code checking tools from complaining.
|
||||
virtual ~array_item_t () ZMQ_DEFAULT;
|
||||
|
||||
void set_array_index (int index_) { _array_index = index_; }
|
||||
|
||||
int get_array_index () const { return _array_index; }
|
||||
|
||||
private:
|
||||
int _array_index;
|
||||
|
||||
ZMQ_NON_COPYABLE_NOR_MOVABLE (array_item_t)
|
||||
};
|
||||
|
||||
|
||||
template <typename T, int ID = 0> class array_t
|
||||
{
|
||||
private:
|
||||
typedef array_item_t<ID> item_t;
|
||||
|
||||
public:
|
||||
typedef typename std::vector<T *>::size_type size_type;
|
||||
|
||||
array_t () ZMQ_DEFAULT;
|
||||
|
||||
size_type size () { return _items.size (); }
|
||||
|
||||
bool empty () { return _items.empty (); }
|
||||
|
||||
T *&operator[] (size_type index_) { return _items[index_]; }
|
||||
|
||||
void push_back (T *item_)
|
||||
{
|
||||
if (item_)
|
||||
static_cast<item_t *> (item_)->set_array_index (
|
||||
static_cast<int> (_items.size ()));
|
||||
_items.push_back (item_);
|
||||
}
|
||||
|
||||
void erase (T *item_)
|
||||
{
|
||||
erase (static_cast<item_t *> (item_)->get_array_index ());
|
||||
}
|
||||
|
||||
void erase (size_type index_)
|
||||
{
|
||||
if (_items.empty ())
|
||||
return;
|
||||
static_cast<item_t *> (_items.back ())
|
||||
->set_array_index (static_cast<int> (index_));
|
||||
|
||||
_items[index_] = _items.back ();
|
||||
_items.pop_back ();
|
||||
}
|
||||
|
||||
void swap (size_type index1_, size_type index2_)
|
||||
{
|
||||
if (_items[index1_])
|
||||
static_cast<item_t *> (_items[index1_])
|
||||
->set_array_index (static_cast<int> (index2_));
|
||||
if (_items[index2_])
|
||||
static_cast<item_t *> (_items[index2_])
|
||||
->set_array_index (static_cast<int> (index1_));
|
||||
std::swap (_items[index1_], _items[index2_]);
|
||||
}
|
||||
|
||||
void clear () { _items.clear (); }
|
||||
|
||||
static size_type index (T *item_)
|
||||
{
|
||||
return static_cast<size_type> (
|
||||
static_cast<item_t *> (item_)->get_array_index ());
|
||||
}
|
||||
|
||||
private:
|
||||
typedef std::vector<T *> items_t;
|
||||
items_t _items;
|
||||
|
||||
ZMQ_NON_COPYABLE_NOR_MOVABLE (array_t)
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
235
3rd/libzmq/src/atomic_counter.hpp
Normal file
235
3rd/libzmq/src/atomic_counter.hpp
Normal file
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ZMQ_ATOMIC_COUNTER_HPP_INCLUDED__
|
||||
#define __ZMQ_ATOMIC_COUNTER_HPP_INCLUDED__
|
||||
|
||||
#include "stdint.hpp"
|
||||
#include "macros.hpp"
|
||||
|
||||
#if defined ZMQ_FORCE_MUTEXES
|
||||
#define ZMQ_ATOMIC_COUNTER_MUTEX
|
||||
#elif (defined __cplusplus && __cplusplus >= 201103L) \
|
||||
|| (defined _MSC_VER && _MSC_VER >= 1900)
|
||||
#define ZMQ_ATOMIC_COUNTER_CXX11
|
||||
#elif defined ZMQ_HAVE_ATOMIC_INTRINSICS
|
||||
#define ZMQ_ATOMIC_COUNTER_INTRINSIC
|
||||
#elif (defined __i386__ || defined __x86_64__) && defined __GNUC__
|
||||
#define ZMQ_ATOMIC_COUNTER_X86
|
||||
#elif defined __ARM_ARCH_7A__ && defined __GNUC__
|
||||
#define ZMQ_ATOMIC_COUNTER_ARM
|
||||
#elif defined ZMQ_HAVE_WINDOWS
|
||||
#define ZMQ_ATOMIC_COUNTER_WINDOWS
|
||||
#elif (defined ZMQ_HAVE_SOLARIS || defined ZMQ_HAVE_NETBSD \
|
||||
|| defined ZMQ_HAVE_GNU)
|
||||
#define ZMQ_ATOMIC_COUNTER_ATOMIC_H
|
||||
#elif defined __tile__
|
||||
#define ZMQ_ATOMIC_COUNTER_TILE
|
||||
#else
|
||||
#define ZMQ_ATOMIC_COUNTER_MUTEX
|
||||
#endif
|
||||
|
||||
#if defined ZMQ_ATOMIC_COUNTER_MUTEX
|
||||
#include "mutex.hpp"
|
||||
#elif defined ZMQ_ATOMIC_COUNTER_CXX11
|
||||
#include <atomic>
|
||||
#elif defined ZMQ_ATOMIC_COUNTER_WINDOWS
|
||||
#include "windows.hpp"
|
||||
#elif defined ZMQ_ATOMIC_COUNTER_ATOMIC_H
|
||||
#include <atomic.h>
|
||||
#elif defined ZMQ_ATOMIC_COUNTER_TILE
|
||||
#include <arch/atomic.h>
|
||||
#endif
|
||||
|
||||
namespace zmq
|
||||
{
|
||||
// This class represents an integer that can be incremented/decremented
|
||||
// in atomic fashion.
|
||||
//
|
||||
// In zmq::shared_message_memory_allocator a buffer with an atomic_counter_t
|
||||
// at the start is allocated. If the class does not align to pointer size,
|
||||
// access to pointers in structures in the buffer will cause SIGBUS on
|
||||
// architectures that do not allow mis-aligned pointers (eg: SPARC).
|
||||
// Force the compiler to align to pointer size, which will cause the object
|
||||
// to grow from 4 bytes to 8 bytes on 64 bit architectures (when not using
|
||||
// mutexes).
|
||||
|
||||
#if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64))
|
||||
class __declspec(align (8)) atomic_counter_t
|
||||
#elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_ARM_ARMV7VE))
|
||||
class __declspec(align (4)) atomic_counter_t
|
||||
#else
|
||||
class atomic_counter_t
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
typedef uint32_t integer_t;
|
||||
|
||||
atomic_counter_t (integer_t value_ = 0) ZMQ_NOEXCEPT : _value (value_) {}
|
||||
|
||||
// Set counter _value (not thread-safe).
|
||||
void set (integer_t value_) ZMQ_NOEXCEPT { _value = value_; }
|
||||
|
||||
// Atomic addition. Returns the old _value.
|
||||
integer_t add (integer_t increment_) ZMQ_NOEXCEPT
|
||||
{
|
||||
integer_t old_value;
|
||||
|
||||
#if defined ZMQ_ATOMIC_COUNTER_WINDOWS
|
||||
old_value = InterlockedExchangeAdd ((LONG *) &_value, increment_);
|
||||
#elif defined ZMQ_ATOMIC_COUNTER_INTRINSIC
|
||||
old_value = __atomic_fetch_add (&_value, increment_, __ATOMIC_ACQ_REL);
|
||||
#elif defined ZMQ_ATOMIC_COUNTER_CXX11
|
||||
old_value = _value.fetch_add (increment_, std::memory_order_acq_rel);
|
||||
#elif defined ZMQ_ATOMIC_COUNTER_ATOMIC_H
|
||||
integer_t new_value = atomic_add_32_nv (&_value, increment_);
|
||||
old_value = new_value - increment_;
|
||||
#elif defined ZMQ_ATOMIC_COUNTER_TILE
|
||||
old_value = arch_atomic_add (&_value, increment_);
|
||||
#elif defined ZMQ_ATOMIC_COUNTER_X86
|
||||
__asm__ volatile("lock; xadd %0, %1 \n\t"
|
||||
: "=r"(old_value), "=m"(_value)
|
||||
: "0"(increment_), "m"(_value)
|
||||
: "cc", "memory");
|
||||
#elif defined ZMQ_ATOMIC_COUNTER_ARM
|
||||
integer_t flag, tmp;
|
||||
__asm__ volatile(" dmb sy\n\t"
|
||||
"1: ldrex %0, [%5]\n\t"
|
||||
" add %2, %0, %4\n\t"
|
||||
" strex %1, %2, [%5]\n\t"
|
||||
" teq %1, #0\n\t"
|
||||
" bne 1b\n\t"
|
||||
" dmb sy\n\t"
|
||||
: "=&r"(old_value), "=&r"(flag), "=&r"(tmp),
|
||||
"+Qo"(_value)
|
||||
: "Ir"(increment_), "r"(&_value)
|
||||
: "cc");
|
||||
#elif defined ZMQ_ATOMIC_COUNTER_MUTEX
|
||||
sync.lock ();
|
||||
old_value = _value;
|
||||
_value += increment_;
|
||||
sync.unlock ();
|
||||
#else
|
||||
#error atomic_counter is not implemented for this platform
|
||||
#endif
|
||||
return old_value;
|
||||
}
|
||||
|
||||
// Atomic subtraction. Returns false if the counter drops to zero.
|
||||
bool sub (integer_t decrement_) ZMQ_NOEXCEPT
|
||||
{
|
||||
#if defined ZMQ_ATOMIC_COUNTER_WINDOWS
|
||||
LONG delta = -((LONG) decrement_);
|
||||
integer_t old = InterlockedExchangeAdd ((LONG *) &_value, delta);
|
||||
return old - decrement_ != 0;
|
||||
#elif defined ZMQ_ATOMIC_COUNTER_INTRINSIC
|
||||
integer_t nv =
|
||||
__atomic_sub_fetch (&_value, decrement_, __ATOMIC_ACQ_REL);
|
||||
return nv != 0;
|
||||
#elif defined ZMQ_ATOMIC_COUNTER_CXX11
|
||||
const integer_t old =
|
||||
_value.fetch_sub (decrement_, std::memory_order_acq_rel);
|
||||
return old - decrement_ != 0;
|
||||
#elif defined ZMQ_ATOMIC_COUNTER_ATOMIC_H
|
||||
int32_t delta = -((int32_t) decrement_);
|
||||
integer_t nv = atomic_add_32_nv (&_value, delta);
|
||||
return nv != 0;
|
||||
#elif defined ZMQ_ATOMIC_COUNTER_TILE
|
||||
int32_t delta = -((int32_t) decrement_);
|
||||
integer_t nv = arch_atomic_add (&_value, delta);
|
||||
return nv != 0;
|
||||
#elif defined ZMQ_ATOMIC_COUNTER_X86
|
||||
integer_t oldval = -decrement_;
|
||||
volatile integer_t *val = &_value;
|
||||
__asm__ volatile("lock; xaddl %0,%1"
|
||||
: "=r"(oldval), "=m"(*val)
|
||||
: "0"(oldval), "m"(*val)
|
||||
: "cc", "memory");
|
||||
return oldval != decrement_;
|
||||
#elif defined ZMQ_ATOMIC_COUNTER_ARM
|
||||
integer_t old_value, flag, tmp;
|
||||
__asm__ volatile(" dmb sy\n\t"
|
||||
"1: ldrex %0, [%5]\n\t"
|
||||
" sub %2, %0, %4\n\t"
|
||||
" strex %1, %2, [%5]\n\t"
|
||||
" teq %1, #0\n\t"
|
||||
" bne 1b\n\t"
|
||||
" dmb sy\n\t"
|
||||
: "=&r"(old_value), "=&r"(flag), "=&r"(tmp),
|
||||
"+Qo"(_value)
|
||||
: "Ir"(decrement_), "r"(&_value)
|
||||
: "cc");
|
||||
return old_value - decrement_ != 0;
|
||||
#elif defined ZMQ_ATOMIC_COUNTER_MUTEX
|
||||
sync.lock ();
|
||||
_value -= decrement_;
|
||||
bool result = _value ? true : false;
|
||||
sync.unlock ();
|
||||
return result;
|
||||
#else
|
||||
#error atomic_counter is not implemented for this platform
|
||||
#endif
|
||||
}
|
||||
|
||||
integer_t get () const ZMQ_NOEXCEPT { return _value; }
|
||||
|
||||
private:
|
||||
#if defined ZMQ_ATOMIC_COUNTER_CXX11
|
||||
std::atomic<integer_t> _value;
|
||||
#else
|
||||
volatile integer_t _value;
|
||||
#endif
|
||||
|
||||
#if defined ZMQ_ATOMIC_COUNTER_MUTEX
|
||||
mutex_t sync;
|
||||
#endif
|
||||
|
||||
#if !defined ZMQ_ATOMIC_COUNTER_CXX11
|
||||
ZMQ_NON_COPYABLE_NOR_MOVABLE (atomic_counter_t)
|
||||
#endif
|
||||
#if defined(__GNUC__) || defined(__INTEL_COMPILER) \
|
||||
|| (defined(__SUNPRO_C) && __SUNPRO_C >= 0x590) \
|
||||
|| (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x590)
|
||||
} __attribute__ ((aligned (sizeof (void *))));
|
||||
#else
|
||||
};
|
||||
#endif
|
||||
}
|
||||
|
||||
// Remove macros local to this file.
|
||||
#undef ZMQ_ATOMIC_COUNTER_MUTEX
|
||||
#undef ZMQ_ATOMIC_COUNTER_INTRINSIC
|
||||
#undef ZMQ_ATOMIC_COUNTER_CXX11
|
||||
#undef ZMQ_ATOMIC_COUNTER_X86
|
||||
#undef ZMQ_ATOMIC_COUNTER_ARM
|
||||
#undef ZMQ_ATOMIC_COUNTER_WINDOWS
|
||||
#undef ZMQ_ATOMIC_COUNTER_ATOMIC_H
|
||||
#undef ZMQ_ATOMIC_COUNTER_TILE
|
||||
|
||||
#endif
|
||||
306
3rd/libzmq/src/atomic_ptr.hpp
Normal file
306
3rd/libzmq/src/atomic_ptr.hpp
Normal file
@@ -0,0 +1,306 @@
|
||||
/*
|
||||
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ZMQ_ATOMIC_PTR_HPP_INCLUDED__
|
||||
#define __ZMQ_ATOMIC_PTR_HPP_INCLUDED__
|
||||
|
||||
#include "macros.hpp"
|
||||
|
||||
#if defined ZMQ_FORCE_MUTEXES
|
||||
#define ZMQ_ATOMIC_PTR_MUTEX
|
||||
#elif (defined __cplusplus && __cplusplus >= 201103L) \
|
||||
|| (defined _MSC_VER && _MSC_VER >= 1900)
|
||||
#define ZMQ_ATOMIC_PTR_CXX11
|
||||
#elif defined ZMQ_HAVE_ATOMIC_INTRINSICS
|
||||
#define ZMQ_ATOMIC_PTR_INTRINSIC
|
||||
#elif (defined __i386__ || defined __x86_64__) && defined __GNUC__
|
||||
#define ZMQ_ATOMIC_PTR_X86
|
||||
#elif defined __ARM_ARCH_7A__ && defined __GNUC__
|
||||
#define ZMQ_ATOMIC_PTR_ARM
|
||||
#elif defined __tile__
|
||||
#define ZMQ_ATOMIC_PTR_TILE
|
||||
#elif defined ZMQ_HAVE_WINDOWS
|
||||
#define ZMQ_ATOMIC_PTR_WINDOWS
|
||||
#elif (defined ZMQ_HAVE_SOLARIS || defined ZMQ_HAVE_NETBSD \
|
||||
|| defined ZMQ_HAVE_GNU)
|
||||
#define ZMQ_ATOMIC_PTR_ATOMIC_H
|
||||
#else
|
||||
#define ZMQ_ATOMIC_PTR_MUTEX
|
||||
#endif
|
||||
|
||||
#if defined ZMQ_ATOMIC_PTR_MUTEX
|
||||
#include "mutex.hpp"
|
||||
#elif defined ZMQ_ATOMIC_PTR_CXX11
|
||||
#include <atomic>
|
||||
#elif defined ZMQ_ATOMIC_PTR_WINDOWS
|
||||
#include "windows.hpp"
|
||||
#elif defined ZMQ_ATOMIC_PTR_ATOMIC_H
|
||||
#include <atomic.h>
|
||||
#elif defined ZMQ_ATOMIC_PTR_TILE
|
||||
#include <arch/atomic.h>
|
||||
#endif
|
||||
|
||||
namespace zmq
|
||||
{
|
||||
#if !defined ZMQ_ATOMIC_PTR_CXX11
|
||||
inline void *atomic_xchg_ptr (void **ptr_,
|
||||
void *const val_
|
||||
#if defined ZMQ_ATOMIC_PTR_MUTEX
|
||||
,
|
||||
mutex_t &_sync
|
||||
#endif
|
||||
) ZMQ_NOEXCEPT
|
||||
{
|
||||
#if defined ZMQ_ATOMIC_PTR_WINDOWS
|
||||
return InterlockedExchangePointer ((PVOID *) ptr_, val_);
|
||||
#elif defined ZMQ_ATOMIC_PTR_INTRINSIC
|
||||
return __atomic_exchange_n (ptr_, val_, __ATOMIC_ACQ_REL);
|
||||
#elif defined ZMQ_ATOMIC_PTR_ATOMIC_H
|
||||
return atomic_swap_ptr (ptr_, val_);
|
||||
#elif defined ZMQ_ATOMIC_PTR_TILE
|
||||
return arch_atomic_exchange (ptr_, val_);
|
||||
#elif defined ZMQ_ATOMIC_PTR_X86
|
||||
void *old;
|
||||
__asm__ volatile("lock; xchg %0, %2"
|
||||
: "=r"(old), "=m"(*ptr_)
|
||||
: "m"(*ptr_), "0"(val_));
|
||||
return old;
|
||||
#elif defined ZMQ_ATOMIC_PTR_ARM
|
||||
void *old;
|
||||
unsigned int flag;
|
||||
__asm__ volatile(" dmb sy\n\t"
|
||||
"1: ldrex %1, [%3]\n\t"
|
||||
" strex %0, %4, [%3]\n\t"
|
||||
" teq %0, #0\n\t"
|
||||
" bne 1b\n\t"
|
||||
" dmb sy\n\t"
|
||||
: "=&r"(flag), "=&r"(old), "+Qo"(*ptr_)
|
||||
: "r"(ptr_), "r"(val_)
|
||||
: "cc");
|
||||
return old;
|
||||
#elif defined ZMQ_ATOMIC_PTR_MUTEX
|
||||
_sync.lock ();
|
||||
void *old = *ptr_;
|
||||
*ptr_ = val_;
|
||||
_sync.unlock ();
|
||||
return old;
|
||||
#else
|
||||
#error atomic_ptr is not implemented for this platform
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void *atomic_cas (void *volatile *ptr_,
|
||||
void *cmp_,
|
||||
void *val_
|
||||
#if defined ZMQ_ATOMIC_PTR_MUTEX
|
||||
,
|
||||
mutex_t &_sync
|
||||
#endif
|
||||
) ZMQ_NOEXCEPT
|
||||
{
|
||||
#if defined ZMQ_ATOMIC_PTR_WINDOWS
|
||||
return InterlockedCompareExchangePointer ((volatile PVOID *) ptr_, val_,
|
||||
cmp_);
|
||||
#elif defined ZMQ_ATOMIC_PTR_INTRINSIC
|
||||
void *old = cmp_;
|
||||
__atomic_compare_exchange_n (ptr_, &old, val_, false, __ATOMIC_RELEASE,
|
||||
__ATOMIC_ACQUIRE);
|
||||
return old;
|
||||
#elif defined ZMQ_ATOMIC_PTR_ATOMIC_H
|
||||
return atomic_cas_ptr (ptr_, cmp_, val_);
|
||||
#elif defined ZMQ_ATOMIC_PTR_TILE
|
||||
return arch_atomic_val_compare_and_exchange (ptr_, cmp_, val_);
|
||||
#elif defined ZMQ_ATOMIC_PTR_X86
|
||||
void *old;
|
||||
__asm__ volatile("lock; cmpxchg %2, %3"
|
||||
: "=a"(old), "=m"(*ptr_)
|
||||
: "r"(val_), "m"(*ptr_), "0"(cmp_)
|
||||
: "cc");
|
||||
return old;
|
||||
#elif defined ZMQ_ATOMIC_PTR_ARM
|
||||
void *old;
|
||||
unsigned int flag;
|
||||
__asm__ volatile(" dmb sy\n\t"
|
||||
"1: ldrex %1, [%3]\n\t"
|
||||
" mov %0, #0\n\t"
|
||||
" teq %1, %4\n\t"
|
||||
" it eq\n\t"
|
||||
" strexeq %0, %5, [%3]\n\t"
|
||||
" teq %0, #0\n\t"
|
||||
" bne 1b\n\t"
|
||||
" dmb sy\n\t"
|
||||
: "=&r"(flag), "=&r"(old), "+Qo"(*ptr_)
|
||||
: "r"(ptr_), "r"(cmp_), "r"(val_)
|
||||
: "cc");
|
||||
return old;
|
||||
#elif defined ZMQ_ATOMIC_PTR_MUTEX
|
||||
_sync.lock ();
|
||||
void *old = *ptr_;
|
||||
if (*ptr_ == cmp_)
|
||||
*ptr_ = val_;
|
||||
_sync.unlock ();
|
||||
return old;
|
||||
#else
|
||||
#error atomic_ptr is not implemented for this platform
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
// This class encapsulates several atomic operations on pointers.
|
||||
|
||||
template <typename T> class atomic_ptr_t
|
||||
{
|
||||
public:
|
||||
// Initialise atomic pointer
|
||||
atomic_ptr_t () ZMQ_NOEXCEPT { _ptr = NULL; }
|
||||
|
||||
// Set value of atomic pointer in a non-threadsafe way
|
||||
// Use this function only when you are sure that at most one
|
||||
// thread is accessing the pointer at the moment.
|
||||
void set (T *ptr_) ZMQ_NOEXCEPT { _ptr = ptr_; }
|
||||
|
||||
// Perform atomic 'exchange pointers' operation. Pointer is set
|
||||
// to the 'val_' value. Old value is returned.
|
||||
T *xchg (T *val_) ZMQ_NOEXCEPT
|
||||
{
|
||||
#if defined ZMQ_ATOMIC_PTR_CXX11
|
||||
return _ptr.exchange (val_, std::memory_order_acq_rel);
|
||||
#else
|
||||
return (T *) atomic_xchg_ptr ((void **) &_ptr, val_
|
||||
#if defined ZMQ_ATOMIC_PTR_MUTEX
|
||||
,
|
||||
_sync
|
||||
#endif
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Perform atomic 'compare and swap' operation on the pointer.
|
||||
// The pointer is compared to 'cmp' argument and if they are
|
||||
// equal, its value is set to 'val_'. Old value of the pointer
|
||||
// is returned.
|
||||
T *cas (T *cmp_, T *val_) ZMQ_NOEXCEPT
|
||||
{
|
||||
#if defined ZMQ_ATOMIC_PTR_CXX11
|
||||
_ptr.compare_exchange_strong (cmp_, val_, std::memory_order_acq_rel);
|
||||
return cmp_;
|
||||
#else
|
||||
return (T *) atomic_cas ((void **) &_ptr, cmp_, val_
|
||||
#if defined ZMQ_ATOMIC_PTR_MUTEX
|
||||
,
|
||||
_sync
|
||||
#endif
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
#if defined ZMQ_ATOMIC_PTR_CXX11
|
||||
std::atomic<T *> _ptr;
|
||||
#else
|
||||
volatile T *_ptr;
|
||||
#endif
|
||||
|
||||
#if defined ZMQ_ATOMIC_PTR_MUTEX
|
||||
mutex_t _sync;
|
||||
#endif
|
||||
|
||||
#if !defined ZMQ_ATOMIC_PTR_CXX11
|
||||
ZMQ_NON_COPYABLE_NOR_MOVABLE (atomic_ptr_t)
|
||||
#endif
|
||||
};
|
||||
|
||||
struct atomic_value_t
|
||||
{
|
||||
atomic_value_t (const int value_) ZMQ_NOEXCEPT : _value (value_) {}
|
||||
|
||||
atomic_value_t (const atomic_value_t &src_) ZMQ_NOEXCEPT
|
||||
: _value (src_.load ())
|
||||
{
|
||||
}
|
||||
|
||||
void store (const int value_) ZMQ_NOEXCEPT
|
||||
{
|
||||
#if defined ZMQ_ATOMIC_PTR_CXX11
|
||||
_value.store (value_, std::memory_order_release);
|
||||
#else
|
||||
atomic_xchg_ptr ((void **) &_value, (void *) (ptrdiff_t) value_
|
||||
#if defined ZMQ_ATOMIC_PTR_MUTEX
|
||||
,
|
||||
_sync
|
||||
#endif
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
int load () const ZMQ_NOEXCEPT
|
||||
{
|
||||
#if defined ZMQ_ATOMIC_PTR_CXX11
|
||||
return _value.load (std::memory_order_acquire);
|
||||
#else
|
||||
return (int) (ptrdiff_t) atomic_cas ((void **) &_value, 0, 0
|
||||
#if defined ZMQ_ATOMIC_PTR_MUTEX
|
||||
,
|
||||
#if defined __SUNPRO_CC
|
||||
const_cast<mutex_t &> (_sync)
|
||||
#else
|
||||
_sync
|
||||
#endif
|
||||
#endif
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
#if defined ZMQ_ATOMIC_PTR_CXX11
|
||||
std::atomic<int> _value;
|
||||
#else
|
||||
volatile ptrdiff_t _value;
|
||||
#endif
|
||||
|
||||
#if defined ZMQ_ATOMIC_PTR_MUTEX
|
||||
mutable mutex_t _sync;
|
||||
#endif
|
||||
|
||||
private:
|
||||
atomic_value_t &operator= (const atomic_value_t &src_);
|
||||
};
|
||||
}
|
||||
|
||||
// Remove macros local to this file.
|
||||
#undef ZMQ_ATOMIC_PTR_MUTEX
|
||||
#undef ZMQ_ATOMIC_PTR_INTRINSIC
|
||||
#undef ZMQ_ATOMIC_PTR_CXX11
|
||||
#undef ZMQ_ATOMIC_PTR_X86
|
||||
#undef ZMQ_ATOMIC_PTR_ARM
|
||||
#undef ZMQ_ATOMIC_PTR_TILE
|
||||
#undef ZMQ_ATOMIC_PTR_WINDOWS
|
||||
#undef ZMQ_ATOMIC_PTR_ATOMIC_H
|
||||
|
||||
#endif
|
||||
205
3rd/libzmq/src/blob.hpp
Normal file
205
3rd/libzmq/src/blob.hpp
Normal file
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ZMQ_BLOB_HPP_INCLUDED__
|
||||
#define __ZMQ_BLOB_HPP_INCLUDED__
|
||||
|
||||
#include "macros.hpp"
|
||||
#include "err.hpp"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <algorithm>
|
||||
#include <ios>
|
||||
|
||||
#if __cplusplus >= 201103L || defined(_MSC_VER) && _MSC_VER > 1700
|
||||
#define ZMQ_HAS_MOVE_SEMANTICS
|
||||
#define ZMQ_MAP_INSERT_OR_EMPLACE(k, v) emplace (k, v)
|
||||
#define ZMQ_PUSH_OR_EMPLACE_BACK emplace_back
|
||||
#define ZMQ_MOVE(x) std::move (x)
|
||||
#else
|
||||
#if defined __SUNPRO_CC
|
||||
template <typename K, typename V>
|
||||
std::pair<const K, V> make_pair_fix_const (const K &k, const V &v)
|
||||
{
|
||||
return std::pair<const K, V> (k, v);
|
||||
}
|
||||
|
||||
#define ZMQ_MAP_INSERT_OR_EMPLACE(k, v) insert (make_pair_fix_const (k, v))
|
||||
#else
|
||||
#define ZMQ_MAP_INSERT_OR_EMPLACE(k, v) insert (std::make_pair (k, v))
|
||||
#endif
|
||||
|
||||
#define ZMQ_PUSH_OR_EMPLACE_BACK push_back
|
||||
#define ZMQ_MOVE(x) (x)
|
||||
#endif
|
||||
|
||||
namespace zmq
|
||||
{
|
||||
struct reference_tag_t
|
||||
{
|
||||
};
|
||||
|
||||
// Object to hold dynamically allocated opaque binary data.
|
||||
// On modern compilers, it will be movable but not copyable. Copies
|
||||
// must be explicitly created by set_deep_copy.
|
||||
// On older compilers, it is copyable for syntactical reasons.
|
||||
struct blob_t
|
||||
{
|
||||
// Creates an empty blob_t.
|
||||
blob_t () : _data (0), _size (0), _owned (true) {}
|
||||
|
||||
// Creates a blob_t of a given size, with uninitialized content.
|
||||
explicit blob_t (const size_t size_) :
|
||||
_data (static_cast<unsigned char *> (malloc (size_))),
|
||||
_size (size_),
|
||||
_owned (true)
|
||||
{
|
||||
alloc_assert (_data);
|
||||
}
|
||||
|
||||
// Creates a blob_t of a given size, an initializes content by copying
|
||||
// from another buffer.
|
||||
blob_t (const unsigned char *const data_, const size_t size_) :
|
||||
_data (static_cast<unsigned char *> (malloc (size_))),
|
||||
_size (size_),
|
||||
_owned (true)
|
||||
{
|
||||
alloc_assert (_data);
|
||||
memcpy (_data, data_, size_);
|
||||
}
|
||||
|
||||
// Creates a blob_t for temporary use that only references a
|
||||
// pre-allocated block of data.
|
||||
// Use with caution and ensure that the blob_t will not outlive
|
||||
// the referenced data.
|
||||
blob_t (unsigned char *const data_, const size_t size_, reference_tag_t) :
|
||||
_data (data_),
|
||||
_size (size_),
|
||||
_owned (false)
|
||||
{
|
||||
}
|
||||
|
||||
// Returns the size of the blob_t.
|
||||
size_t size () const { return _size; }
|
||||
|
||||
// Returns a pointer to the data of the blob_t.
|
||||
const unsigned char *data () const { return _data; }
|
||||
|
||||
// Returns a pointer to the data of the blob_t.
|
||||
unsigned char *data () { return _data; }
|
||||
|
||||
// Defines an order relationship on blob_t.
|
||||
bool operator< (blob_t const &other_) const
|
||||
{
|
||||
const int cmpres =
|
||||
memcmp (_data, other_._data, std::min (_size, other_._size));
|
||||
return cmpres < 0 || (cmpres == 0 && _size < other_._size);
|
||||
}
|
||||
|
||||
// Sets a blob_t to a deep copy of another blob_t.
|
||||
void set_deep_copy (blob_t const &other_)
|
||||
{
|
||||
clear ();
|
||||
_data = static_cast<unsigned char *> (malloc (other_._size));
|
||||
alloc_assert (_data);
|
||||
_size = other_._size;
|
||||
_owned = true;
|
||||
memcpy (_data, other_._data, _size);
|
||||
}
|
||||
|
||||
// Sets a blob_t to a copy of a given buffer.
|
||||
void set (const unsigned char *const data_, const size_t size_)
|
||||
{
|
||||
clear ();
|
||||
_data = static_cast<unsigned char *> (malloc (size_));
|
||||
alloc_assert (_data);
|
||||
_size = size_;
|
||||
_owned = true;
|
||||
memcpy (_data, data_, size_);
|
||||
}
|
||||
|
||||
// Empties a blob_t.
|
||||
void clear ()
|
||||
{
|
||||
if (_owned) {
|
||||
free (_data);
|
||||
}
|
||||
_data = 0;
|
||||
_size = 0;
|
||||
}
|
||||
|
||||
~blob_t ()
|
||||
{
|
||||
if (_owned) {
|
||||
free (_data);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ZMQ_HAS_MOVE_SEMANTICS
|
||||
blob_t (const blob_t &) = delete;
|
||||
blob_t &operator= (const blob_t &) = delete;
|
||||
|
||||
blob_t (blob_t &&other_) ZMQ_NOEXCEPT : _data (other_._data),
|
||||
_size (other_._size),
|
||||
_owned (other_._owned)
|
||||
{
|
||||
other_._owned = false;
|
||||
}
|
||||
blob_t &operator= (blob_t &&other_) ZMQ_NOEXCEPT
|
||||
{
|
||||
if (this != &other_) {
|
||||
clear ();
|
||||
_data = other_._data;
|
||||
_size = other_._size;
|
||||
_owned = other_._owned;
|
||||
other_._owned = false;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
#else
|
||||
blob_t (const blob_t &other) : _owned (false) { set_deep_copy (other); }
|
||||
blob_t &operator= (const blob_t &other)
|
||||
{
|
||||
if (this != &other) {
|
||||
clear ();
|
||||
set_deep_copy (other);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
unsigned char *_data;
|
||||
size_t _size;
|
||||
bool _owned;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
160
3rd/libzmq/src/channel.cpp
Normal file
160
3rd/libzmq/src/channel.cpp
Normal file
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
Copyright (c) 2007-2020 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "macros.hpp"
|
||||
#include "channel.hpp"
|
||||
#include "err.hpp"
|
||||
#include "pipe.hpp"
|
||||
#include "msg.hpp"
|
||||
|
||||
zmq::channel_t::channel_t (class ctx_t *parent_, uint32_t tid_, int sid_) :
|
||||
socket_base_t (parent_, tid_, sid_, true),
|
||||
_pipe (NULL)
|
||||
{
|
||||
options.type = ZMQ_CHANNEL;
|
||||
}
|
||||
|
||||
zmq::channel_t::~channel_t ()
|
||||
{
|
||||
zmq_assert (!_pipe);
|
||||
}
|
||||
|
||||
void zmq::channel_t::xattach_pipe (pipe_t *pipe_,
|
||||
bool subscribe_to_all_,
|
||||
bool locally_initiated_)
|
||||
{
|
||||
LIBZMQ_UNUSED (subscribe_to_all_);
|
||||
LIBZMQ_UNUSED (locally_initiated_);
|
||||
|
||||
zmq_assert (pipe_ != NULL);
|
||||
|
||||
// ZMQ_PAIR socket can only be connected to a single peer.
|
||||
// The socket rejects any further connection requests.
|
||||
if (_pipe == NULL)
|
||||
_pipe = pipe_;
|
||||
else
|
||||
pipe_->terminate (false);
|
||||
}
|
||||
|
||||
void zmq::channel_t::xpipe_terminated (pipe_t *pipe_)
|
||||
{
|
||||
if (pipe_ == _pipe)
|
||||
_pipe = NULL;
|
||||
}
|
||||
|
||||
void zmq::channel_t::xread_activated (pipe_t *)
|
||||
{
|
||||
// There's just one pipe. No lists of active and inactive pipes.
|
||||
// There's nothing to do here.
|
||||
}
|
||||
|
||||
void zmq::channel_t::xwrite_activated (pipe_t *)
|
||||
{
|
||||
// There's just one pipe. No lists of active and inactive pipes.
|
||||
// There's nothing to do here.
|
||||
}
|
||||
|
||||
int zmq::channel_t::xsend (msg_t *msg_)
|
||||
{
|
||||
// CHANNEL sockets do not allow multipart data (ZMQ_SNDMORE)
|
||||
if (msg_->flags () & msg_t::more) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!_pipe || !_pipe->write (msg_)) {
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
_pipe->flush ();
|
||||
|
||||
// Detach the original message from the data buffer.
|
||||
const int rc = msg_->init ();
|
||||
errno_assert (rc == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int zmq::channel_t::xrecv (msg_t *msg_)
|
||||
{
|
||||
// Deallocate old content of the message.
|
||||
int rc = msg_->close ();
|
||||
errno_assert (rc == 0);
|
||||
|
||||
if (!_pipe) {
|
||||
// Initialise the output parameter to be a 0-byte message.
|
||||
rc = msg_->init ();
|
||||
errno_assert (rc == 0);
|
||||
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Drop any messages with more flag
|
||||
bool read = _pipe->read (msg_);
|
||||
while (read && msg_->flags () & msg_t::more) {
|
||||
// drop all frames of the current multi-frame message
|
||||
read = _pipe->read (msg_);
|
||||
while (read && msg_->flags () & msg_t::more)
|
||||
read = _pipe->read (msg_);
|
||||
|
||||
// get the new message
|
||||
if (read)
|
||||
read = _pipe->read (msg_);
|
||||
}
|
||||
|
||||
if (!read) {
|
||||
// Initialise the output parameter to be a 0-byte message.
|
||||
rc = msg_->init ();
|
||||
errno_assert (rc == 0);
|
||||
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool zmq::channel_t::xhas_in ()
|
||||
{
|
||||
if (!_pipe)
|
||||
return false;
|
||||
|
||||
return _pipe->check_read ();
|
||||
}
|
||||
|
||||
bool zmq::channel_t::xhas_out ()
|
||||
{
|
||||
if (!_pipe)
|
||||
return false;
|
||||
|
||||
return _pipe->check_write ();
|
||||
}
|
||||
69
3rd/libzmq/src/channel.hpp
Normal file
69
3rd/libzmq/src/channel.hpp
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
Copyright (c) 2007-2020 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ZMQ_CHANNEL_HPP_INCLUDED__
|
||||
#define __ZMQ_CHANNEL_HPP_INCLUDED__
|
||||
|
||||
#include "blob.hpp"
|
||||
#include "socket_base.hpp"
|
||||
#include "session_base.hpp"
|
||||
|
||||
namespace zmq
|
||||
{
|
||||
class ctx_t;
|
||||
class msg_t;
|
||||
class pipe_t;
|
||||
class io_thread_t;
|
||||
|
||||
class channel_t ZMQ_FINAL : public socket_base_t
|
||||
{
|
||||
public:
|
||||
channel_t (zmq::ctx_t *parent_, uint32_t tid_, int sid_);
|
||||
~channel_t ();
|
||||
|
||||
// Overrides of functions from socket_base_t.
|
||||
void xattach_pipe (zmq::pipe_t *pipe_,
|
||||
bool subscribe_to_all_,
|
||||
bool locally_initiated_);
|
||||
int xsend (zmq::msg_t *msg_);
|
||||
int xrecv (zmq::msg_t *msg_);
|
||||
bool xhas_in ();
|
||||
bool xhas_out ();
|
||||
void xread_activated (zmq::pipe_t *pipe_);
|
||||
void xwrite_activated (zmq::pipe_t *pipe_);
|
||||
void xpipe_terminated (zmq::pipe_t *pipe_);
|
||||
|
||||
private:
|
||||
zmq::pipe_t *_pipe;
|
||||
|
||||
ZMQ_NON_COPYABLE_NOR_MOVABLE (channel_t)
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
114
3rd/libzmq/src/client.cpp
Normal file
114
3rd/libzmq/src/client.cpp
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "macros.hpp"
|
||||
#include "client.hpp"
|
||||
#include "err.hpp"
|
||||
#include "msg.hpp"
|
||||
|
||||
zmq::client_t::client_t (class ctx_t *parent_, uint32_t tid_, int sid_) :
|
||||
socket_base_t (parent_, tid_, sid_, true)
|
||||
{
|
||||
options.type = ZMQ_CLIENT;
|
||||
options.can_send_hello_msg = true;
|
||||
}
|
||||
|
||||
zmq::client_t::~client_t ()
|
||||
{
|
||||
}
|
||||
|
||||
void zmq::client_t::xattach_pipe (pipe_t *pipe_,
|
||||
bool subscribe_to_all_,
|
||||
bool locally_initiated_)
|
||||
{
|
||||
LIBZMQ_UNUSED (subscribe_to_all_);
|
||||
LIBZMQ_UNUSED (locally_initiated_);
|
||||
|
||||
zmq_assert (pipe_);
|
||||
|
||||
_fq.attach (pipe_);
|
||||
_lb.attach (pipe_);
|
||||
}
|
||||
|
||||
int zmq::client_t::xsend (msg_t *msg_)
|
||||
{
|
||||
// CLIENT sockets do not allow multipart data (ZMQ_SNDMORE)
|
||||
if (msg_->flags () & msg_t::more) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
return _lb.sendpipe (msg_, NULL);
|
||||
}
|
||||
|
||||
int zmq::client_t::xrecv (msg_t *msg_)
|
||||
{
|
||||
int rc = _fq.recvpipe (msg_, NULL);
|
||||
|
||||
// Drop any messages with more flag
|
||||
while (rc == 0 && msg_->flags () & msg_t::more) {
|
||||
// drop all frames of the current multi-frame message
|
||||
rc = _fq.recvpipe (msg_, NULL);
|
||||
|
||||
while (rc == 0 && msg_->flags () & msg_t::more)
|
||||
rc = _fq.recvpipe (msg_, NULL);
|
||||
|
||||
// get the new message
|
||||
if (rc == 0)
|
||||
rc = _fq.recvpipe (msg_, NULL);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
bool zmq::client_t::xhas_in ()
|
||||
{
|
||||
return _fq.has_in ();
|
||||
}
|
||||
|
||||
bool zmq::client_t::xhas_out ()
|
||||
{
|
||||
return _lb.has_out ();
|
||||
}
|
||||
|
||||
void zmq::client_t::xread_activated (pipe_t *pipe_)
|
||||
{
|
||||
_fq.activated (pipe_);
|
||||
}
|
||||
|
||||
void zmq::client_t::xwrite_activated (pipe_t *pipe_)
|
||||
{
|
||||
_lb.activated (pipe_);
|
||||
}
|
||||
|
||||
void zmq::client_t::xpipe_terminated (pipe_t *pipe_)
|
||||
{
|
||||
_fq.pipe_terminated (pipe_);
|
||||
_lb.pipe_terminated (pipe_);
|
||||
}
|
||||
73
3rd/libzmq/src/client.hpp
Normal file
73
3rd/libzmq/src/client.hpp
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ZMQ_CLIENT_HPP_INCLUDED__
|
||||
#define __ZMQ_CLIENT_HPP_INCLUDED__
|
||||
|
||||
#include "socket_base.hpp"
|
||||
#include "fq.hpp"
|
||||
#include "lb.hpp"
|
||||
|
||||
namespace zmq
|
||||
{
|
||||
class ctx_t;
|
||||
class msg_t;
|
||||
class pipe_t;
|
||||
class io_thread_t;
|
||||
|
||||
class client_t ZMQ_FINAL : public socket_base_t
|
||||
{
|
||||
public:
|
||||
client_t (zmq::ctx_t *parent_, uint32_t tid_, int sid_);
|
||||
~client_t ();
|
||||
|
||||
protected:
|
||||
// Overrides of functions from socket_base_t.
|
||||
void xattach_pipe (zmq::pipe_t *pipe_,
|
||||
bool subscribe_to_all_,
|
||||
bool locally_initiated_);
|
||||
int xsend (zmq::msg_t *msg_);
|
||||
int xrecv (zmq::msg_t *msg_);
|
||||
bool xhas_in ();
|
||||
bool xhas_out ();
|
||||
void xread_activated (zmq::pipe_t *pipe_);
|
||||
void xwrite_activated (zmq::pipe_t *pipe_);
|
||||
void xpipe_terminated (zmq::pipe_t *pipe_);
|
||||
|
||||
private:
|
||||
// Messages are fair-queued from inbound pipes. And load-balanced to
|
||||
// the outbound pipes.
|
||||
fq_t _fq;
|
||||
lb_t _lb;
|
||||
|
||||
ZMQ_NON_COPYABLE_NOR_MOVABLE (client_t)
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
277
3rd/libzmq/src/clock.cpp
Normal file
277
3rd/libzmq/src/clock.cpp
Normal file
@@ -0,0 +1,277 @@
|
||||
/*
|
||||
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "clock.hpp"
|
||||
#include "likely.hpp"
|
||||
#include "config.hpp"
|
||||
#include "err.hpp"
|
||||
#include "mutex.hpp"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#if defined _MSC_VER
|
||||
#if defined _WIN32_WCE
|
||||
#include <cmnintrin.h>
|
||||
#else
|
||||
#include <intrin.h>
|
||||
#if defined(_M_ARM) || defined(_M_ARM64)
|
||||
#include <arm_neon.h>
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined ZMQ_HAVE_WINDOWS
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#if defined HAVE_CLOCK_GETTIME || defined HAVE_GETHRTIME
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
#if defined ZMQ_HAVE_VXWORKS
|
||||
#include "timers.h"
|
||||
#endif
|
||||
|
||||
#if defined ZMQ_HAVE_OSX
|
||||
int alt_clock_gettime (int clock_id, timespec *ts)
|
||||
{
|
||||
clock_serv_t cclock;
|
||||
mach_timespec_t mts;
|
||||
host_get_clock_service (mach_host_self (), clock_id, &cclock);
|
||||
clock_get_time (cclock, &mts);
|
||||
mach_port_deallocate (mach_task_self (), cclock);
|
||||
ts->tv_sec = mts.tv_sec;
|
||||
ts->tv_nsec = mts.tv_nsec;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ZMQ_HAVE_WINDOWS
|
||||
typedef ULONGLONG (*f_compatible_get_tick_count64) ();
|
||||
|
||||
static zmq::mutex_t compatible_get_tick_count64_mutex;
|
||||
|
||||
ULONGLONG compatible_get_tick_count64 ()
|
||||
{
|
||||
#ifdef ZMQ_HAVE_WINDOWS_UWP
|
||||
const ULONGLONG result = ::GetTickCount64 ();
|
||||
return result;
|
||||
#else
|
||||
zmq::scoped_lock_t locker (compatible_get_tick_count64_mutex);
|
||||
|
||||
static DWORD s_wrap = 0;
|
||||
static DWORD s_last_tick = 0;
|
||||
const DWORD current_tick = ::GetTickCount ();
|
||||
|
||||
if (current_tick < s_last_tick)
|
||||
++s_wrap;
|
||||
|
||||
s_last_tick = current_tick;
|
||||
const ULONGLONG result = (static_cast<ULONGLONG> (s_wrap) << 32)
|
||||
+ static_cast<ULONGLONG> (current_tick);
|
||||
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
f_compatible_get_tick_count64 init_compatible_get_tick_count64 ()
|
||||
{
|
||||
f_compatible_get_tick_count64 func = NULL;
|
||||
#if !defined ZMQ_HAVE_WINDOWS_UWP
|
||||
|
||||
const HMODULE module = ::LoadLibraryA ("Kernel32.dll");
|
||||
if (module != NULL)
|
||||
func = reinterpret_cast<f_compatible_get_tick_count64> (
|
||||
::GetProcAddress (module, "GetTickCount64"));
|
||||
#endif
|
||||
if (func == NULL)
|
||||
func = compatible_get_tick_count64;
|
||||
|
||||
#if !defined ZMQ_HAVE_WINDOWS_UWP
|
||||
if (module != NULL)
|
||||
::FreeLibrary (module);
|
||||
#endif
|
||||
|
||||
return func;
|
||||
}
|
||||
|
||||
static f_compatible_get_tick_count64 my_get_tick_count64 =
|
||||
init_compatible_get_tick_count64 ();
|
||||
#endif
|
||||
|
||||
const uint64_t usecs_per_msec = 1000;
|
||||
const uint64_t usecs_per_sec = 1000000;
|
||||
const uint64_t nsecs_per_usec = 1000;
|
||||
|
||||
zmq::clock_t::clock_t () :
|
||||
_last_tsc (rdtsc ()),
|
||||
#ifdef ZMQ_HAVE_WINDOWS
|
||||
_last_time (static_cast<uint64_t> ((*my_get_tick_count64) ()))
|
||||
#else
|
||||
_last_time (now_us () / usecs_per_msec)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
uint64_t zmq::clock_t::now_us ()
|
||||
{
|
||||
#if defined ZMQ_HAVE_WINDOWS
|
||||
|
||||
// Get the high resolution counter's accuracy.
|
||||
// While QueryPerformanceFrequency only needs to be called once, since its
|
||||
// value does not change during runtime, we query it here since this is a
|
||||
// static function. It might make sense to cache it, though.
|
||||
LARGE_INTEGER ticks_per_second;
|
||||
QueryPerformanceFrequency (&ticks_per_second);
|
||||
|
||||
// What time is it?
|
||||
LARGE_INTEGER tick;
|
||||
QueryPerformanceCounter (&tick);
|
||||
|
||||
// Convert the tick number into the number of seconds
|
||||
// since the system was started.
|
||||
const double ticks_div =
|
||||
static_cast<double> (ticks_per_second.QuadPart) / usecs_per_sec;
|
||||
return static_cast<uint64_t> (tick.QuadPart / ticks_div);
|
||||
|
||||
#elif defined HAVE_CLOCK_GETTIME \
|
||||
&& (defined CLOCK_MONOTONIC || defined ZMQ_HAVE_VXWORKS)
|
||||
|
||||
// Use POSIX clock_gettime function to get precise monotonic time.
|
||||
struct timespec tv;
|
||||
|
||||
#if defined ZMQ_HAVE_OSX \
|
||||
&& __MAC_OS_X_VERSION_MIN_REQUIRED < 101200 // less than macOS 10.12
|
||||
int rc = alt_clock_gettime (SYSTEM_CLOCK, &tv);
|
||||
#else
|
||||
int rc = clock_gettime (CLOCK_MONOTONIC, &tv);
|
||||
#endif
|
||||
// Fix case where system has clock_gettime but CLOCK_MONOTONIC is not supported.
|
||||
// This should be a configuration check, but I looked into it and writing an
|
||||
// AC_FUNC_CLOCK_MONOTONIC seems beyond my powers.
|
||||
if (rc != 0) {
|
||||
#ifndef ZMQ_HAVE_VXWORKS
|
||||
// Use POSIX gettimeofday function to get precise time.
|
||||
struct timeval tv;
|
||||
int rc = gettimeofday (&tv, NULL);
|
||||
errno_assert (rc == 0);
|
||||
return tv.tv_sec * usecs_per_sec + tv.tv_usec;
|
||||
#endif
|
||||
}
|
||||
return tv.tv_sec * usecs_per_sec + tv.tv_nsec / nsecs_per_usec;
|
||||
|
||||
#elif defined HAVE_GETHRTIME
|
||||
|
||||
return gethrtime () / nsecs_per_usec;
|
||||
|
||||
#else
|
||||
|
||||
// Use POSIX gettimeofday function to get precise time.
|
||||
struct timeval tv;
|
||||
int rc = gettimeofday (&tv, NULL);
|
||||
errno_assert (rc == 0);
|
||||
return tv.tv_sec * usecs_per_sec + tv.tv_usec;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
uint64_t zmq::clock_t::now_ms ()
|
||||
{
|
||||
const uint64_t tsc = rdtsc ();
|
||||
|
||||
// If TSC is not supported, get precise time and chop off the microseconds.
|
||||
if (!tsc) {
|
||||
#ifdef ZMQ_HAVE_WINDOWS
|
||||
// Under Windows, now_us is not so reliable since QueryPerformanceCounter
|
||||
// does not guarantee that it will use a hardware that offers a monotonic timer.
|
||||
// So, lets use GetTickCount when GetTickCount64 is not available with an workaround
|
||||
// to its 32 bit limitation.
|
||||
return static_cast<uint64_t> ((*my_get_tick_count64) ());
|
||||
#else
|
||||
return now_us () / usecs_per_msec;
|
||||
#endif
|
||||
}
|
||||
|
||||
// If TSC haven't jumped back (in case of migration to a different
|
||||
// CPU core) and if not too much time elapsed since last measurement,
|
||||
// we can return cached time value.
|
||||
if (likely (tsc - _last_tsc <= (clock_precision / 2) && tsc >= _last_tsc))
|
||||
return _last_time;
|
||||
|
||||
_last_tsc = tsc;
|
||||
#ifdef ZMQ_HAVE_WINDOWS
|
||||
_last_time = static_cast<uint64_t> ((*my_get_tick_count64) ());
|
||||
#else
|
||||
_last_time = now_us () / usecs_per_msec;
|
||||
#endif
|
||||
return _last_time;
|
||||
}
|
||||
|
||||
uint64_t zmq::clock_t::rdtsc ()
|
||||
{
|
||||
#if (defined _MSC_VER && (defined _M_IX86 || defined _M_X64))
|
||||
return __rdtsc ();
|
||||
#elif defined(_MSC_VER) && defined(_M_ARM) // NC => added for windows ARM
|
||||
return __rdpmccntr64 ();
|
||||
#elif defined(_MSC_VER) && defined(_M_ARM64) // NC => added for windows ARM64
|
||||
//return __rdpmccntr64 ();
|
||||
//return __rdtscp (nullptr);
|
||||
// todo: find proper implementation for ARM64
|
||||
static uint64_t snCounter = 0;
|
||||
return ++snCounter;
|
||||
#elif (defined __GNUC__ && (defined __i386__ || defined __x86_64__))
|
||||
uint32_t low, high;
|
||||
__asm__ volatile("rdtsc" : "=a"(low), "=d"(high));
|
||||
return static_cast<uint64_t> (high) << 32 | low;
|
||||
#elif (defined __SUNPRO_CC && (__SUNPRO_CC >= 0x5100) \
|
||||
&& (defined __i386 || defined __amd64 || defined __x86_64))
|
||||
union
|
||||
{
|
||||
uint64_t u64val;
|
||||
uint32_t u32val[2];
|
||||
} tsc;
|
||||
asm("rdtsc" : "=a"(tsc.u32val[0]), "=d"(tsc.u32val[1]));
|
||||
return tsc.u64val;
|
||||
#elif defined(__s390__)
|
||||
uint64_t tsc;
|
||||
asm("\tstck\t%0\n" : "=Q"(tsc) : : "cc");
|
||||
return tsc;
|
||||
#else
|
||||
struct timespec ts;
|
||||
#if defined ZMQ_HAVE_OSX \
|
||||
&& __MAC_OS_X_VERSION_MIN_REQUIRED < 101200 // less than macOS 10.12
|
||||
alt_clock_gettime (SYSTEM_CLOCK, &ts);
|
||||
#else
|
||||
clock_gettime (CLOCK_MONOTONIC, &ts);
|
||||
#endif
|
||||
return static_cast<uint64_t> (ts.tv_sec) * nsecs_per_usec * usecs_per_sec
|
||||
+ ts.tv_nsec;
|
||||
#endif
|
||||
}
|
||||
80
3rd/libzmq/src/clock.hpp
Normal file
80
3rd/libzmq/src/clock.hpp
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ZMQ_CLOCK_HPP_INCLUDED__
|
||||
#define __ZMQ_CLOCK_HPP_INCLUDED__
|
||||
|
||||
#include "macros.hpp"
|
||||
#include "stdint.hpp"
|
||||
|
||||
#if defined ZMQ_HAVE_OSX
|
||||
// TODO this is not required in this file, but condition_variable.hpp includes
|
||||
// clock.hpp to get these definitions
|
||||
#ifndef CLOCK_REALTIME
|
||||
#define CLOCK_REALTIME 0
|
||||
#endif
|
||||
#ifndef HAVE_CLOCK_GETTIME
|
||||
#define HAVE_CLOCK_GETTIME
|
||||
#endif
|
||||
|
||||
#include <mach/clock.h>
|
||||
#include <mach/mach.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
namespace zmq
|
||||
{
|
||||
class clock_t
|
||||
{
|
||||
public:
|
||||
clock_t ();
|
||||
|
||||
// CPU's timestamp counter. Returns 0 if it's not available.
|
||||
static uint64_t rdtsc ();
|
||||
|
||||
// High precision timestamp.
|
||||
static uint64_t now_us ();
|
||||
|
||||
// Low precision timestamp. In tight loops generating it can be
|
||||
// 10 to 100 times faster than the high precision timestamp.
|
||||
uint64_t now_ms ();
|
||||
|
||||
private:
|
||||
// TSC timestamp of when last time measurement was made.
|
||||
uint64_t _last_tsc;
|
||||
|
||||
// Physical time corresponding to the TSC above (in milliseconds).
|
||||
uint64_t _last_time;
|
||||
|
||||
ZMQ_NON_COPYABLE_NOR_MOVABLE (clock_t)
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
225
3rd/libzmq/src/command.hpp
Normal file
225
3rd/libzmq/src/command.hpp
Normal file
@@ -0,0 +1,225 @@
|
||||
/*
|
||||
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ZMQ_COMMAND_HPP_INCLUDED__
|
||||
#define __ZMQ_COMMAND_HPP_INCLUDED__
|
||||
|
||||
#include <string>
|
||||
#include "stdint.hpp"
|
||||
#include "endpoint.hpp"
|
||||
|
||||
namespace zmq
|
||||
{
|
||||
class object_t;
|
||||
class own_t;
|
||||
struct i_engine;
|
||||
class pipe_t;
|
||||
class socket_base_t;
|
||||
|
||||
// This structure defines the commands that can be sent between threads.
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4324) // C4324: alignment padding warnings
|
||||
__declspec(align (64))
|
||||
#endif
|
||||
struct command_t
|
||||
{
|
||||
// Object to process the command.
|
||||
zmq::object_t *destination;
|
||||
|
||||
enum type_t
|
||||
{
|
||||
stop,
|
||||
plug,
|
||||
own,
|
||||
attach,
|
||||
bind,
|
||||
activate_read,
|
||||
activate_write,
|
||||
hiccup,
|
||||
pipe_term,
|
||||
pipe_term_ack,
|
||||
pipe_hwm,
|
||||
term_req,
|
||||
term,
|
||||
term_ack,
|
||||
term_endpoint,
|
||||
reap,
|
||||
reaped,
|
||||
inproc_connected,
|
||||
conn_failed,
|
||||
pipe_peer_stats,
|
||||
pipe_stats_publish,
|
||||
done
|
||||
} type;
|
||||
|
||||
union args_t
|
||||
{
|
||||
// Sent to I/O thread to let it know that it should
|
||||
// terminate itself.
|
||||
struct
|
||||
{
|
||||
} stop;
|
||||
|
||||
// Sent to I/O object to make it register with its I/O thread.
|
||||
struct
|
||||
{
|
||||
} plug;
|
||||
|
||||
// Sent to socket to let it know about the newly created object.
|
||||
struct
|
||||
{
|
||||
zmq::own_t *object;
|
||||
} own;
|
||||
|
||||
// Attach the engine to the session. If engine is NULL, it informs
|
||||
// session that the connection have failed.
|
||||
struct
|
||||
{
|
||||
struct i_engine *engine;
|
||||
} attach;
|
||||
|
||||
// Sent from session to socket to establish pipe(s) between them.
|
||||
// Caller have used inc_seqnum beforehand sending the command.
|
||||
struct
|
||||
{
|
||||
zmq::pipe_t *pipe;
|
||||
} bind;
|
||||
|
||||
// Sent by pipe writer to inform dormant pipe reader that there
|
||||
// are messages in the pipe.
|
||||
struct
|
||||
{
|
||||
} activate_read;
|
||||
|
||||
// Sent by pipe reader to inform pipe writer about how many
|
||||
// messages it has read so far.
|
||||
struct
|
||||
{
|
||||
uint64_t msgs_read;
|
||||
} activate_write;
|
||||
|
||||
// Sent by pipe reader to writer after creating a new inpipe.
|
||||
// The parameter is actually of type pipe_t::upipe_t, however,
|
||||
// its definition is private so we'll have to do with void*.
|
||||
struct
|
||||
{
|
||||
void *pipe;
|
||||
} hiccup;
|
||||
|
||||
// Sent by pipe reader to pipe writer to ask it to terminate
|
||||
// its end of the pipe.
|
||||
struct
|
||||
{
|
||||
} pipe_term;
|
||||
|
||||
// Pipe writer acknowledges pipe_term command.
|
||||
struct
|
||||
{
|
||||
} pipe_term_ack;
|
||||
|
||||
// Sent by one of pipe to another part for modify hwm
|
||||
struct
|
||||
{
|
||||
int inhwm;
|
||||
int outhwm;
|
||||
} pipe_hwm;
|
||||
|
||||
// Sent by I/O object ot the socket to request the shutdown of
|
||||
// the I/O object.
|
||||
struct
|
||||
{
|
||||
zmq::own_t *object;
|
||||
} term_req;
|
||||
|
||||
// Sent by socket to I/O object to start its shutdown.
|
||||
struct
|
||||
{
|
||||
int linger;
|
||||
} term;
|
||||
|
||||
// Sent by I/O object to the socket to acknowledge it has
|
||||
// shut down.
|
||||
struct
|
||||
{
|
||||
} term_ack;
|
||||
|
||||
// Sent by session_base (I/O thread) to socket (application thread)
|
||||
// to ask to disconnect the endpoint.
|
||||
struct
|
||||
{
|
||||
std::string *endpoint;
|
||||
} term_endpoint;
|
||||
|
||||
// Transfers the ownership of the closed socket
|
||||
// to the reaper thread.
|
||||
struct
|
||||
{
|
||||
zmq::socket_base_t *socket;
|
||||
} reap;
|
||||
|
||||
// Closed socket notifies the reaper that it's already deallocated.
|
||||
struct
|
||||
{
|
||||
} reaped;
|
||||
|
||||
// Send application-side pipe count and ask to send monitor event
|
||||
struct
|
||||
{
|
||||
uint64_t queue_count;
|
||||
zmq::own_t *socket_base;
|
||||
endpoint_uri_pair_t *endpoint_pair;
|
||||
} pipe_peer_stats;
|
||||
|
||||
// Collate application thread and I/O thread pipe counts and endpoints
|
||||
// and send as event
|
||||
struct
|
||||
{
|
||||
uint64_t outbound_queue_count;
|
||||
uint64_t inbound_queue_count;
|
||||
endpoint_uri_pair_t *endpoint_pair;
|
||||
} pipe_stats_publish;
|
||||
|
||||
// Sent by reaper thread to the term thread when all the sockets
|
||||
// are successfully deallocated.
|
||||
struct
|
||||
{
|
||||
} done;
|
||||
|
||||
} args;
|
||||
#ifdef _MSC_VER
|
||||
};
|
||||
#pragma warning(pop)
|
||||
#else
|
||||
} __attribute__ ((aligned (64)));
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
75
3rd/libzmq/src/compat.hpp
Normal file
75
3rd/libzmq/src/compat.hpp
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
Copyright (c) 2020 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ZMQ_COMPAT_HPP_INCLUDED__
|
||||
#define __ZMQ_COMPAT_HPP_INCLUDED__
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include <string.h>
|
||||
|
||||
#ifdef ZMQ_HAVE_WINDOWS
|
||||
#define strcasecmp _stricmp
|
||||
#define strtok_r strtok_s
|
||||
#else
|
||||
#ifndef ZMQ_HAVE_STRLCPY
|
||||
#ifdef ZMQ_HAVE_LIBBSD
|
||||
#include <bsd/string.h>
|
||||
#else
|
||||
static inline size_t
|
||||
strlcpy (char *dest_, const char *src_, const size_t dest_size_)
|
||||
{
|
||||
size_t remain = dest_size_;
|
||||
for (; remain && *src_; --remain, ++src_, ++dest_) {
|
||||
*dest_ = *src_;
|
||||
}
|
||||
return dest_size_ - remain;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
template <size_t size>
|
||||
static inline int strcpy_s (char (&dest_)[size], const char *const src_)
|
||||
{
|
||||
const size_t res = strlcpy (dest_, src_, size);
|
||||
return res >= size ? ERANGE : 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRNLEN
|
||||
static inline size_t strnlen (const char *s, size_t len)
|
||||
{
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
if (s[i] == '\0')
|
||||
return i + 1;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
313
3rd/libzmq/src/condition_variable.hpp
Normal file
313
3rd/libzmq/src/condition_variable.hpp
Normal file
@@ -0,0 +1,313 @@
|
||||
/*
|
||||
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ZMQ_CONDITON_VARIABLE_HPP_INCLUDED__
|
||||
#define __ZMQ_CONDITON_VARIABLE_HPP_INCLUDED__
|
||||
|
||||
#include "err.hpp"
|
||||
#include "mutex.hpp"
|
||||
|
||||
// Condition variable class encapsulates OS mutex in a platform-independent way.
|
||||
|
||||
#if defined(ZMQ_USE_CV_IMPL_NONE)
|
||||
|
||||
namespace zmq
|
||||
{
|
||||
class condition_variable_t
|
||||
{
|
||||
public:
|
||||
inline condition_variable_t () { zmq_assert (false); }
|
||||
|
||||
inline int wait (mutex_t *mutex_, int timeout_)
|
||||
{
|
||||
zmq_assert (false);
|
||||
return -1;
|
||||
}
|
||||
|
||||
inline void broadcast () { zmq_assert (false); }
|
||||
|
||||
ZMQ_NON_COPYABLE_NOR_MOVABLE (condition_variable_t)
|
||||
};
|
||||
}
|
||||
|
||||
#elif defined(ZMQ_USE_CV_IMPL_WIN32API)
|
||||
|
||||
#include "windows.hpp"
|
||||
|
||||
namespace zmq
|
||||
{
|
||||
class condition_variable_t
|
||||
{
|
||||
public:
|
||||
inline condition_variable_t () { InitializeConditionVariable (&_cv); }
|
||||
|
||||
inline int wait (mutex_t *mutex_, int timeout_)
|
||||
{
|
||||
int rc = SleepConditionVariableCS (&_cv, mutex_->get_cs (), timeout_);
|
||||
|
||||
if (rc != 0)
|
||||
return 0;
|
||||
|
||||
rc = GetLastError ();
|
||||
|
||||
if (rc != ERROR_TIMEOUT)
|
||||
win_assert (rc);
|
||||
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
inline void broadcast () { WakeAllConditionVariable (&_cv); }
|
||||
|
||||
private:
|
||||
CONDITION_VARIABLE _cv;
|
||||
|
||||
ZMQ_NON_COPYABLE_NOR_MOVABLE (condition_variable_t)
|
||||
};
|
||||
}
|
||||
|
||||
#elif defined(ZMQ_USE_CV_IMPL_STL11)
|
||||
|
||||
#include <condition_variable>
|
||||
|
||||
namespace zmq
|
||||
{
|
||||
class condition_variable_t
|
||||
{
|
||||
public:
|
||||
condition_variable_t () ZMQ_DEFAULT;
|
||||
|
||||
int wait (mutex_t *mutex_, int timeout_)
|
||||
{
|
||||
// this assumes that the mutex mutex_ has been locked by the caller
|
||||
int res = 0;
|
||||
if (timeout_ == -1) {
|
||||
_cv.wait (
|
||||
*mutex_); // unlock mtx and wait cv.notify_all(), lock mtx after cv.notify_all()
|
||||
} else if (_cv.wait_for (*mutex_, std::chrono::milliseconds (timeout_))
|
||||
== std::cv_status::timeout) {
|
||||
// time expired
|
||||
errno = EAGAIN;
|
||||
res = -1;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void broadcast ()
|
||||
{
|
||||
// this assumes that the mutex associated with _cv has been locked by the caller
|
||||
_cv.notify_all ();
|
||||
}
|
||||
|
||||
private:
|
||||
std::condition_variable_any _cv;
|
||||
|
||||
ZMQ_NON_COPYABLE_NOR_MOVABLE (condition_variable_t)
|
||||
};
|
||||
}
|
||||
|
||||
#elif defined(ZMQ_USE_CV_IMPL_VXWORKS)
|
||||
|
||||
#include <sysLib.h>
|
||||
|
||||
namespace zmq
|
||||
{
|
||||
class condition_variable_t
|
||||
{
|
||||
public:
|
||||
inline condition_variable_t () ZMQ_DEFAULT;
|
||||
|
||||
inline ~condition_variable_t ()
|
||||
{
|
||||
scoped_lock_t l (_listenersMutex);
|
||||
for (size_t i = 0; i < _listeners.size (); i++) {
|
||||
semDelete (_listeners[i]);
|
||||
}
|
||||
}
|
||||
|
||||
inline int wait (mutex_t *mutex_, int timeout_)
|
||||
{
|
||||
//Atomically releases lock, blocks the current executing thread,
|
||||
//and adds it to the list of threads waiting on *this. The thread
|
||||
//will be unblocked when broadcast() is executed.
|
||||
//It may also be unblocked spuriously. When unblocked, regardless
|
||||
//of the reason, lock is reacquired and wait exits.
|
||||
|
||||
SEM_ID sem = semBCreate (SEM_Q_PRIORITY, SEM_EMPTY);
|
||||
{
|
||||
scoped_lock_t l (_listenersMutex);
|
||||
_listeners.push_back (sem);
|
||||
}
|
||||
mutex_->unlock ();
|
||||
|
||||
int rc;
|
||||
if (timeout_ < 0)
|
||||
rc = semTake (sem, WAIT_FOREVER);
|
||||
else {
|
||||
int ticksPerSec = sysClkRateGet ();
|
||||
int timeoutTicks = (timeout_ * ticksPerSec) / 1000 + 1;
|
||||
rc = semTake (sem, timeoutTicks);
|
||||
}
|
||||
|
||||
{
|
||||
scoped_lock_t l (_listenersMutex);
|
||||
// remove sem from listeners
|
||||
for (size_t i = 0; i < _listeners.size (); i++) {
|
||||
if (_listeners[i] == sem) {
|
||||
_listeners.erase (_listeners.begin () + i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
semDelete (sem);
|
||||
}
|
||||
mutex_->lock ();
|
||||
|
||||
if (rc == 0)
|
||||
return 0;
|
||||
|
||||
if (rc == S_objLib_OBJ_TIMEOUT) {
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
inline void broadcast ()
|
||||
{
|
||||
scoped_lock_t l (_listenersMutex);
|
||||
for (size_t i = 0; i < _listeners.size (); i++) {
|
||||
semGive (_listeners[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
mutex_t _listenersMutex;
|
||||
std::vector<SEM_ID> _listeners;
|
||||
|
||||
ZMQ_NON_COPYABLE_NOR_MOVABLE (condition_variable_t)
|
||||
};
|
||||
}
|
||||
|
||||
#elif defined(ZMQ_USE_CV_IMPL_PTHREADS)
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#if defined(__ANDROID_API__) && __ANDROID_API__ < 21
|
||||
#define ANDROID_LEGACY
|
||||
extern "C" int pthread_cond_timedwait_monotonic_np (pthread_cond_t *,
|
||||
pthread_mutex_t *,
|
||||
const struct timespec *);
|
||||
#endif
|
||||
|
||||
namespace zmq
|
||||
{
|
||||
class condition_variable_t
|
||||
{
|
||||
public:
|
||||
inline condition_variable_t ()
|
||||
{
|
||||
pthread_condattr_t attr;
|
||||
pthread_condattr_init (&attr);
|
||||
#if !defined(ZMQ_HAVE_OSX) && !defined(ANDROID_LEGACY)
|
||||
pthread_condattr_setclock (&attr, CLOCK_MONOTONIC);
|
||||
#endif
|
||||
int rc = pthread_cond_init (&_cond, &attr);
|
||||
posix_assert (rc);
|
||||
}
|
||||
|
||||
inline ~condition_variable_t ()
|
||||
{
|
||||
int rc = pthread_cond_destroy (&_cond);
|
||||
posix_assert (rc);
|
||||
}
|
||||
|
||||
inline int wait (mutex_t *mutex_, int timeout_)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (timeout_ != -1) {
|
||||
struct timespec timeout;
|
||||
|
||||
#ifdef ZMQ_HAVE_OSX
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_nsec = 0;
|
||||
#else
|
||||
rc = clock_gettime (CLOCK_MONOTONIC, &timeout);
|
||||
posix_assert (rc);
|
||||
#endif
|
||||
|
||||
timeout.tv_sec += timeout_ / 1000;
|
||||
timeout.tv_nsec += (timeout_ % 1000) * 1000000;
|
||||
|
||||
if (timeout.tv_nsec >= 1000000000) {
|
||||
timeout.tv_sec++;
|
||||
timeout.tv_nsec -= 1000000000;
|
||||
}
|
||||
#ifdef ZMQ_HAVE_OSX
|
||||
rc = pthread_cond_timedwait_relative_np (
|
||||
&_cond, mutex_->get_mutex (), &timeout);
|
||||
#elif defined(ANDROID_LEGACY)
|
||||
rc = pthread_cond_timedwait_monotonic_np (
|
||||
&_cond, mutex_->get_mutex (), &timeout);
|
||||
#else
|
||||
rc =
|
||||
pthread_cond_timedwait (&_cond, mutex_->get_mutex (), &timeout);
|
||||
#endif
|
||||
} else
|
||||
rc = pthread_cond_wait (&_cond, mutex_->get_mutex ());
|
||||
|
||||
if (rc == 0)
|
||||
return 0;
|
||||
|
||||
if (rc == ETIMEDOUT) {
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
posix_assert (rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
inline void broadcast ()
|
||||
{
|
||||
int rc = pthread_cond_broadcast (&_cond);
|
||||
posix_assert (rc);
|
||||
}
|
||||
|
||||
private:
|
||||
pthread_cond_t _cond;
|
||||
|
||||
ZMQ_NON_COPYABLE_NOR_MOVABLE (condition_variable_t)
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
89
3rd/libzmq/src/config.hpp
Normal file
89
3rd/libzmq/src/config.hpp
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ZMQ_CONFIG_HPP_INCLUDED__
|
||||
#define __ZMQ_CONFIG_HPP_INCLUDED__
|
||||
|
||||
namespace zmq
|
||||
{
|
||||
// Compile-time settings.
|
||||
|
||||
enum
|
||||
{
|
||||
// Number of new messages in message pipe needed to trigger new memory
|
||||
// allocation. Setting this parameter to 256 decreases the impact of
|
||||
// memory allocation by approximately 99.6%
|
||||
message_pipe_granularity = 256,
|
||||
|
||||
// Commands in pipe per allocation event.
|
||||
command_pipe_granularity = 16,
|
||||
|
||||
// Determines how often does socket poll for new commands when it
|
||||
// still has unprocessed messages to handle. Thus, if it is set to 100,
|
||||
// socket will process 100 inbound messages before doing the poll.
|
||||
// If there are no unprocessed messages available, poll is done
|
||||
// immediately. Decreasing the value trades overall latency for more
|
||||
// real-time behaviour (less latency peaks).
|
||||
inbound_poll_rate = 100,
|
||||
|
||||
// Maximal delta between high and low watermark.
|
||||
max_wm_delta = 1024,
|
||||
|
||||
// Maximum number of events the I/O thread can process in one go.
|
||||
max_io_events = 256,
|
||||
|
||||
// Maximal batch size of packets forwarded by a ZMQ proxy.
|
||||
// Increasing this value improves throughput at the expense of
|
||||
// latency and fairness.
|
||||
proxy_burst_size = 1000,
|
||||
|
||||
// Maximal delay to process command in API thread (in CPU ticks).
|
||||
// 3,000,000 ticks equals to 1 - 2 milliseconds on current CPUs.
|
||||
// Note that delay is only applied when there is continuous stream of
|
||||
// messages to process. If not so, commands are processed immediately.
|
||||
max_command_delay = 3000000,
|
||||
|
||||
// Low-precision clock precision in CPU ticks. 1ms. Value of 1000000
|
||||
// should be OK for CPU frequencies above 1GHz. If should work
|
||||
// reasonably well for CPU frequencies above 500MHz. For lower CPU
|
||||
// frequencies you may consider lowering this value to get best
|
||||
// possible latencies.
|
||||
clock_precision = 1000000,
|
||||
|
||||
// On some OSes the signaler has to be emulated using a TCP
|
||||
// connection. In such cases following port is used.
|
||||
// If 0, it lets the OS choose a free port without requiring use of a
|
||||
// global mutex. The original implementation of a Windows signaler
|
||||
// socket used port 5905 instead of letting the OS choose a free port.
|
||||
// https://github.com/zeromq/libzmq/issues/1542
|
||||
signaler_port = 0
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
893
3rd/libzmq/src/ctx.cpp
Normal file
893
3rd/libzmq/src/ctx.cpp
Normal file
@@ -0,0 +1,893 @@
|
||||
/*
|
||||
Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "macros.hpp"
|
||||
#ifndef ZMQ_HAVE_WINDOWS
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <limits>
|
||||
#include <climits>
|
||||
#include <new>
|
||||
#include <sstream>
|
||||
#include <string.h>
|
||||
|
||||
#include "ctx.hpp"
|
||||
#include "socket_base.hpp"
|
||||
#include "io_thread.hpp"
|
||||
#include "reaper.hpp"
|
||||
#include "pipe.hpp"
|
||||
#include "err.hpp"
|
||||
#include "msg.hpp"
|
||||
#include "random.hpp"
|
||||
|
||||
#ifdef ZMQ_HAVE_VMCI
|
||||
#include <vmci_sockets.h>
|
||||
#endif
|
||||
|
||||
#ifdef ZMQ_USE_NSS
|
||||
#include <nss.h>
|
||||
#endif
|
||||
|
||||
#ifdef ZMQ_USE_GNUTLS
|
||||
#include <gnutls/gnutls.h>
|
||||
#endif
|
||||
|
||||
#define ZMQ_CTX_TAG_VALUE_GOOD 0xabadcafe
|
||||
#define ZMQ_CTX_TAG_VALUE_BAD 0xdeadbeef
|
||||
|
||||
static int clipped_maxsocket (int max_requested_)
|
||||
{
|
||||
if (max_requested_ >= zmq::poller_t::max_fds ()
|
||||
&& zmq::poller_t::max_fds () != -1)
|
||||
// -1 because we need room for the reaper mailbox.
|
||||
max_requested_ = zmq::poller_t::max_fds () - 1;
|
||||
|
||||
return max_requested_;
|
||||
}
|
||||
|
||||
zmq::ctx_t::ctx_t () :
|
||||
_tag (ZMQ_CTX_TAG_VALUE_GOOD),
|
||||
_starting (true),
|
||||
_terminating (false),
|
||||
_reaper (NULL),
|
||||
_max_sockets (clipped_maxsocket (ZMQ_MAX_SOCKETS_DFLT)),
|
||||
_max_msgsz (INT_MAX),
|
||||
_io_thread_count (ZMQ_IO_THREADS_DFLT),
|
||||
_blocky (true),
|
||||
_ipv6 (false),
|
||||
_zero_copy (true)
|
||||
{
|
||||
#ifdef HAVE_FORK
|
||||
_pid = getpid ();
|
||||
#endif
|
||||
#ifdef ZMQ_HAVE_VMCI
|
||||
_vmci_fd = -1;
|
||||
_vmci_family = -1;
|
||||
#endif
|
||||
|
||||
// Initialise crypto library, if needed.
|
||||
zmq::random_open ();
|
||||
|
||||
#ifdef ZMQ_USE_NSS
|
||||
NSS_NoDB_Init (NULL);
|
||||
#endif
|
||||
|
||||
#ifdef ZMQ_USE_GNUTLS
|
||||
gnutls_global_init ();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool zmq::ctx_t::check_tag () const
|
||||
{
|
||||
return _tag == ZMQ_CTX_TAG_VALUE_GOOD;
|
||||
}
|
||||
|
||||
zmq::ctx_t::~ctx_t ()
|
||||
{
|
||||
// Check that there are no remaining _sockets.
|
||||
zmq_assert (_sockets.empty ());
|
||||
|
||||
// Ask I/O threads to terminate. If stop signal wasn't sent to I/O
|
||||
// thread subsequent invocation of destructor would hang-up.
|
||||
const io_threads_t::size_type io_threads_size = _io_threads.size ();
|
||||
for (io_threads_t::size_type i = 0; i != io_threads_size; i++) {
|
||||
_io_threads[i]->stop ();
|
||||
}
|
||||
|
||||
// Wait till I/O threads actually terminate.
|
||||
for (io_threads_t::size_type i = 0; i != io_threads_size; i++) {
|
||||
LIBZMQ_DELETE (_io_threads[i]);
|
||||
}
|
||||
|
||||
// Deallocate the reaper thread object.
|
||||
LIBZMQ_DELETE (_reaper);
|
||||
|
||||
// The mailboxes in _slots themselves were deallocated with their
|
||||
// corresponding io_thread/socket objects.
|
||||
|
||||
// De-initialise crypto library, if needed.
|
||||
zmq::random_close ();
|
||||
|
||||
#ifdef ZMQ_USE_NSS
|
||||
NSS_Shutdown ();
|
||||
#endif
|
||||
|
||||
#ifdef ZMQ_USE_GNUTLS
|
||||
gnutls_global_deinit ();
|
||||
#endif
|
||||
|
||||
// Remove the tag, so that the object is considered dead.
|
||||
_tag = ZMQ_CTX_TAG_VALUE_BAD;
|
||||
}
|
||||
|
||||
bool zmq::ctx_t::valid () const
|
||||
{
|
||||
return _term_mailbox.valid ();
|
||||
}
|
||||
|
||||
int zmq::ctx_t::terminate ()
|
||||
{
|
||||
_slot_sync.lock ();
|
||||
|
||||
const bool save_terminating = _terminating;
|
||||
_terminating = false;
|
||||
|
||||
// Connect up any pending inproc connections, otherwise we will hang
|
||||
pending_connections_t copy = _pending_connections;
|
||||
for (pending_connections_t::iterator p = copy.begin (), end = copy.end ();
|
||||
p != end; ++p) {
|
||||
zmq::socket_base_t *s = create_socket (ZMQ_PAIR);
|
||||
// create_socket might fail eg: out of memory/sockets limit reached
|
||||
zmq_assert (s);
|
||||
s->bind (p->first.c_str ());
|
||||
s->close ();
|
||||
}
|
||||
_terminating = save_terminating;
|
||||
|
||||
if (!_starting) {
|
||||
#ifdef HAVE_FORK
|
||||
if (_pid != getpid ()) {
|
||||
// we are a forked child process. Close all file descriptors
|
||||
// inherited from the parent.
|
||||
for (sockets_t::size_type i = 0, size = _sockets.size (); i != size;
|
||||
i++) {
|
||||
_sockets[i]->get_mailbox ()->forked ();
|
||||
}
|
||||
_term_mailbox.forked ();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Check whether termination was already underway, but interrupted and now
|
||||
// restarted.
|
||||
const bool restarted = _terminating;
|
||||
_terminating = true;
|
||||
|
||||
// First attempt to terminate the context.
|
||||
if (!restarted) {
|
||||
// First send stop command to sockets so that any blocking calls
|
||||
// can be interrupted. If there are no sockets we can ask reaper
|
||||
// thread to stop.
|
||||
for (sockets_t::size_type i = 0, size = _sockets.size (); i != size;
|
||||
i++) {
|
||||
_sockets[i]->stop ();
|
||||
}
|
||||
if (_sockets.empty ())
|
||||
_reaper->stop ();
|
||||
}
|
||||
_slot_sync.unlock ();
|
||||
|
||||
// Wait till reaper thread closes all the sockets.
|
||||
command_t cmd;
|
||||
const int rc = _term_mailbox.recv (&cmd, -1);
|
||||
if (rc == -1 && errno == EINTR)
|
||||
return -1;
|
||||
errno_assert (rc == 0);
|
||||
zmq_assert (cmd.type == command_t::done);
|
||||
_slot_sync.lock ();
|
||||
zmq_assert (_sockets.empty ());
|
||||
}
|
||||
_slot_sync.unlock ();
|
||||
|
||||
#ifdef ZMQ_HAVE_VMCI
|
||||
_vmci_sync.lock ();
|
||||
|
||||
VMCISock_ReleaseAFValueFd (_vmci_fd);
|
||||
_vmci_family = -1;
|
||||
_vmci_fd = -1;
|
||||
|
||||
_vmci_sync.unlock ();
|
||||
#endif
|
||||
|
||||
// Deallocate the resources.
|
||||
delete this;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int zmq::ctx_t::shutdown ()
|
||||
{
|
||||
scoped_lock_t locker (_slot_sync);
|
||||
|
||||
if (!_terminating) {
|
||||
_terminating = true;
|
||||
|
||||
if (!_starting) {
|
||||
// Send stop command to sockets so that any blocking calls
|
||||
// can be interrupted. If there are no sockets we can ask reaper
|
||||
// thread to stop.
|
||||
for (sockets_t::size_type i = 0, size = _sockets.size (); i != size;
|
||||
i++) {
|
||||
_sockets[i]->stop ();
|
||||
}
|
||||
if (_sockets.empty ())
|
||||
_reaper->stop ();
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int zmq::ctx_t::set (int option_, const void *optval_, size_t optvallen_)
|
||||
{
|
||||
const bool is_int = (optvallen_ == sizeof (int));
|
||||
int value = 0;
|
||||
if (is_int)
|
||||
memcpy (&value, optval_, sizeof (int));
|
||||
|
||||
switch (option_) {
|
||||
case ZMQ_MAX_SOCKETS:
|
||||
if (is_int && value >= 1 && value == clipped_maxsocket (value)) {
|
||||
scoped_lock_t locker (_opt_sync);
|
||||
_max_sockets = value;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case ZMQ_IO_THREADS:
|
||||
if (is_int && value >= 0) {
|
||||
scoped_lock_t locker (_opt_sync);
|
||||
_io_thread_count = value;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case ZMQ_IPV6:
|
||||
if (is_int && value >= 0) {
|
||||
scoped_lock_t locker (_opt_sync);
|
||||
_ipv6 = (value != 0);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case ZMQ_BLOCKY:
|
||||
if (is_int && value >= 0) {
|
||||
scoped_lock_t locker (_opt_sync);
|
||||
_blocky = (value != 0);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case ZMQ_MAX_MSGSZ:
|
||||
if (is_int && value >= 0) {
|
||||
scoped_lock_t locker (_opt_sync);
|
||||
_max_msgsz = value < INT_MAX ? value : INT_MAX;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case ZMQ_ZERO_COPY_RECV:
|
||||
if (is_int && value >= 0) {
|
||||
scoped_lock_t locker (_opt_sync);
|
||||
_zero_copy = (value != 0);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default: {
|
||||
return thread_ctx_t::set (option_, optval_, optvallen_);
|
||||
}
|
||||
}
|
||||
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int zmq::ctx_t::get (int option_, void *optval_, const size_t *optvallen_)
|
||||
{
|
||||
const bool is_int = (*optvallen_ == sizeof (int));
|
||||
int *value = static_cast<int *> (optval_);
|
||||
|
||||
switch (option_) {
|
||||
case ZMQ_MAX_SOCKETS:
|
||||
if (is_int) {
|
||||
*value = _max_sockets;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case ZMQ_SOCKET_LIMIT:
|
||||
if (is_int) {
|
||||
*value = clipped_maxsocket (65535);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case ZMQ_IO_THREADS:
|
||||
if (is_int) {
|
||||
*value = _io_thread_count;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case ZMQ_IPV6:
|
||||
if (is_int) {
|
||||
*value = _ipv6;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case ZMQ_BLOCKY:
|
||||
if (is_int) {
|
||||
*value = _blocky;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case ZMQ_MAX_MSGSZ:
|
||||
if (is_int) {
|
||||
*value = _max_msgsz;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case ZMQ_MSG_T_SIZE:
|
||||
if (is_int) {
|
||||
*value = sizeof (zmq_msg_t);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case ZMQ_ZERO_COPY_RECV:
|
||||
if (is_int) {
|
||||
*value = _zero_copy;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default: {
|
||||
return thread_ctx_t::get (option_, optval_, optvallen_);
|
||||
}
|
||||
}
|
||||
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int zmq::ctx_t::get (int option_)
|
||||
{
|
||||
int optval = 0;
|
||||
size_t optvallen = sizeof (int);
|
||||
|
||||
if (get (option_, &optval, &optvallen) == 0)
|
||||
return optval;
|
||||
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool zmq::ctx_t::start ()
|
||||
{
|
||||
// Initialise the array of mailboxes. Additional two slots are for
|
||||
// zmq_ctx_term thread and reaper thread.
|
||||
_opt_sync.lock ();
|
||||
const int term_and_reaper_threads_count = 2;
|
||||
const int mazmq = _max_sockets;
|
||||
const int ios = _io_thread_count;
|
||||
_opt_sync.unlock ();
|
||||
const int slot_count = mazmq + ios + term_and_reaper_threads_count;
|
||||
try {
|
||||
_slots.reserve (slot_count);
|
||||
_empty_slots.reserve (slot_count - term_and_reaper_threads_count);
|
||||
}
|
||||
catch (const std::bad_alloc &) {
|
||||
errno = ENOMEM;
|
||||
return false;
|
||||
}
|
||||
_slots.resize (term_and_reaper_threads_count);
|
||||
|
||||
// Initialise the infrastructure for zmq_ctx_term thread.
|
||||
_slots[term_tid] = &_term_mailbox;
|
||||
|
||||
// Create the reaper thread.
|
||||
_reaper = new (std::nothrow) reaper_t (this, reaper_tid);
|
||||
if (!_reaper) {
|
||||
errno = ENOMEM;
|
||||
goto fail_cleanup_slots;
|
||||
}
|
||||
if (!_reaper->get_mailbox ()->valid ())
|
||||
goto fail_cleanup_reaper;
|
||||
_slots[reaper_tid] = _reaper->get_mailbox ();
|
||||
_reaper->start ();
|
||||
|
||||
// Create I/O thread objects and launch them.
|
||||
_slots.resize (slot_count, NULL);
|
||||
|
||||
for (int i = term_and_reaper_threads_count;
|
||||
i != ios + term_and_reaper_threads_count; i++) {
|
||||
io_thread_t *io_thread = new (std::nothrow) io_thread_t (this, i);
|
||||
if (!io_thread) {
|
||||
errno = ENOMEM;
|
||||
goto fail_cleanup_reaper;
|
||||
}
|
||||
if (!io_thread->get_mailbox ()->valid ()) {
|
||||
delete io_thread;
|
||||
goto fail_cleanup_reaper;
|
||||
}
|
||||
_io_threads.push_back (io_thread);
|
||||
_slots[i] = io_thread->get_mailbox ();
|
||||
io_thread->start ();
|
||||
}
|
||||
|
||||
// In the unused part of the slot array, create a list of empty slots.
|
||||
for (int32_t i = static_cast<int32_t> (_slots.size ()) - 1;
|
||||
i >= static_cast<int32_t> (ios) + term_and_reaper_threads_count; i--) {
|
||||
_empty_slots.push_back (i);
|
||||
}
|
||||
|
||||
_starting = false;
|
||||
return true;
|
||||
|
||||
fail_cleanup_reaper:
|
||||
_reaper->stop ();
|
||||
delete _reaper;
|
||||
_reaper = NULL;
|
||||
|
||||
fail_cleanup_slots:
|
||||
_slots.clear ();
|
||||
return false;
|
||||
}
|
||||
|
||||
zmq::socket_base_t *zmq::ctx_t::create_socket (int type_)
|
||||
{
|
||||
scoped_lock_t locker (_slot_sync);
|
||||
|
||||
// Once zmq_ctx_term() or zmq_ctx_shutdown() was called, we can't create
|
||||
// new sockets.
|
||||
if (_terminating) {
|
||||
errno = ETERM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (unlikely (_starting)) {
|
||||
if (!start ())
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// If max_sockets limit was reached, return error.
|
||||
if (_empty_slots.empty ()) {
|
||||
errno = EMFILE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Choose a slot for the socket.
|
||||
const uint32_t slot = _empty_slots.back ();
|
||||
_empty_slots.pop_back ();
|
||||
|
||||
// Generate new unique socket ID.
|
||||
const int sid = (static_cast<int> (max_socket_id.add (1))) + 1;
|
||||
|
||||
// Create the socket and register its mailbox.
|
||||
socket_base_t *s = socket_base_t::create (type_, this, slot, sid);
|
||||
if (!s) {
|
||||
_empty_slots.push_back (slot);
|
||||
return NULL;
|
||||
}
|
||||
_sockets.push_back (s);
|
||||
_slots[slot] = s->get_mailbox ();
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void zmq::ctx_t::destroy_socket (class socket_base_t *socket_)
|
||||
{
|
||||
scoped_lock_t locker (_slot_sync);
|
||||
|
||||
// Free the associated thread slot.
|
||||
const uint32_t tid = socket_->get_tid ();
|
||||
_empty_slots.push_back (tid);
|
||||
_slots[tid] = NULL;
|
||||
|
||||
// Remove the socket from the list of sockets.
|
||||
_sockets.erase (socket_);
|
||||
|
||||
// If zmq_ctx_term() was already called and there are no more socket
|
||||
// we can ask reaper thread to terminate.
|
||||
if (_terminating && _sockets.empty ())
|
||||
_reaper->stop ();
|
||||
}
|
||||
|
||||
zmq::object_t *zmq::ctx_t::get_reaper () const
|
||||
{
|
||||
return _reaper;
|
||||
}
|
||||
|
||||
zmq::thread_ctx_t::thread_ctx_t () :
|
||||
_thread_priority (ZMQ_THREAD_PRIORITY_DFLT),
|
||||
_thread_sched_policy (ZMQ_THREAD_SCHED_POLICY_DFLT)
|
||||
{
|
||||
}
|
||||
|
||||
void zmq::thread_ctx_t::start_thread (thread_t &thread_,
|
||||
thread_fn *tfn_,
|
||||
void *arg_,
|
||||
const char *name_) const
|
||||
{
|
||||
thread_.setSchedulingParameters (_thread_priority, _thread_sched_policy,
|
||||
_thread_affinity_cpus);
|
||||
|
||||
char namebuf[16] = "";
|
||||
snprintf (namebuf, sizeof (namebuf), "%s%sZMQbg%s%s",
|
||||
_thread_name_prefix.empty () ? "" : _thread_name_prefix.c_str (),
|
||||
_thread_name_prefix.empty () ? "" : "/", name_ ? "/" : "",
|
||||
name_ ? name_ : "");
|
||||
thread_.start (tfn_, arg_, namebuf);
|
||||
}
|
||||
|
||||
int zmq::thread_ctx_t::set (int option_, const void *optval_, size_t optvallen_)
|
||||
{
|
||||
const bool is_int = (optvallen_ == sizeof (int));
|
||||
int value = 0;
|
||||
if (is_int)
|
||||
memcpy (&value, optval_, sizeof (int));
|
||||
|
||||
switch (option_) {
|
||||
case ZMQ_THREAD_SCHED_POLICY:
|
||||
if (is_int && value >= 0) {
|
||||
scoped_lock_t locker (_opt_sync);
|
||||
_thread_sched_policy = value;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case ZMQ_THREAD_AFFINITY_CPU_ADD:
|
||||
if (is_int && value >= 0) {
|
||||
scoped_lock_t locker (_opt_sync);
|
||||
_thread_affinity_cpus.insert (value);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case ZMQ_THREAD_AFFINITY_CPU_REMOVE:
|
||||
if (is_int && value >= 0) {
|
||||
scoped_lock_t locker (_opt_sync);
|
||||
if (0 == _thread_affinity_cpus.erase (value)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case ZMQ_THREAD_PRIORITY:
|
||||
if (is_int && value >= 0) {
|
||||
scoped_lock_t locker (_opt_sync);
|
||||
_thread_priority = value;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case ZMQ_THREAD_NAME_PREFIX:
|
||||
// start_thread() allows max 16 chars for thread name
|
||||
if (is_int) {
|
||||
std::ostringstream s;
|
||||
s << value;
|
||||
scoped_lock_t locker (_opt_sync);
|
||||
_thread_name_prefix = s.str ();
|
||||
return 0;
|
||||
} else if (optvallen_ > 0 && optvallen_ <= 16) {
|
||||
scoped_lock_t locker (_opt_sync);
|
||||
_thread_name_prefix.assign (static_cast<const char *> (optval_),
|
||||
optvallen_);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int zmq::thread_ctx_t::get (int option_,
|
||||
void *optval_,
|
||||
const size_t *optvallen_)
|
||||
{
|
||||
const bool is_int = (*optvallen_ == sizeof (int));
|
||||
int *value = static_cast<int *> (optval_);
|
||||
|
||||
switch (option_) {
|
||||
case ZMQ_THREAD_SCHED_POLICY:
|
||||
if (is_int) {
|
||||
scoped_lock_t locker (_opt_sync);
|
||||
*value = _thread_sched_policy;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case ZMQ_THREAD_NAME_PREFIX:
|
||||
if (is_int) {
|
||||
scoped_lock_t locker (_opt_sync);
|
||||
*value = atoi (_thread_name_prefix.c_str ());
|
||||
return 0;
|
||||
} else if (*optvallen_ >= _thread_name_prefix.size ()) {
|
||||
scoped_lock_t locker (_opt_sync);
|
||||
memcpy (optval_, _thread_name_prefix.data (),
|
||||
_thread_name_prefix.size ());
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void zmq::ctx_t::send_command (uint32_t tid_, const command_t &command_)
|
||||
{
|
||||
_slots[tid_]->send (command_);
|
||||
}
|
||||
|
||||
zmq::io_thread_t *zmq::ctx_t::choose_io_thread (uint64_t affinity_)
|
||||
{
|
||||
if (_io_threads.empty ())
|
||||
return NULL;
|
||||
|
||||
// Find the I/O thread with minimum load.
|
||||
int min_load = -1;
|
||||
io_thread_t *selected_io_thread = NULL;
|
||||
for (io_threads_t::size_type i = 0, size = _io_threads.size (); i != size;
|
||||
i++) {
|
||||
if (!affinity_ || (affinity_ & (uint64_t (1) << i))) {
|
||||
const int load = _io_threads[i]->get_load ();
|
||||
if (selected_io_thread == NULL || load < min_load) {
|
||||
min_load = load;
|
||||
selected_io_thread = _io_threads[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return selected_io_thread;
|
||||
}
|
||||
|
||||
int zmq::ctx_t::register_endpoint (const char *addr_,
|
||||
const endpoint_t &endpoint_)
|
||||
{
|
||||
scoped_lock_t locker (_endpoints_sync);
|
||||
|
||||
const bool inserted =
|
||||
_endpoints.ZMQ_MAP_INSERT_OR_EMPLACE (std::string (addr_), endpoint_)
|
||||
.second;
|
||||
if (!inserted) {
|
||||
errno = EADDRINUSE;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int zmq::ctx_t::unregister_endpoint (const std::string &addr_,
|
||||
const socket_base_t *const socket_)
|
||||
{
|
||||
scoped_lock_t locker (_endpoints_sync);
|
||||
|
||||
const endpoints_t::iterator it = _endpoints.find (addr_);
|
||||
if (it == _endpoints.end () || it->second.socket != socket_) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Remove endpoint.
|
||||
_endpoints.erase (it);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void zmq::ctx_t::unregister_endpoints (const socket_base_t *const socket_)
|
||||
{
|
||||
scoped_lock_t locker (_endpoints_sync);
|
||||
|
||||
for (endpoints_t::iterator it = _endpoints.begin (),
|
||||
end = _endpoints.end ();
|
||||
it != end;) {
|
||||
if (it->second.socket == socket_)
|
||||
#if __cplusplus >= 201103L || (defined _MSC_VER && _MSC_VER >= 1700)
|
||||
it = _endpoints.erase (it);
|
||||
#else
|
||||
_endpoints.erase (it++);
|
||||
#endif
|
||||
else
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
zmq::endpoint_t zmq::ctx_t::find_endpoint (const char *addr_)
|
||||
{
|
||||
scoped_lock_t locker (_endpoints_sync);
|
||||
|
||||
endpoints_t::iterator it = _endpoints.find (addr_);
|
||||
if (it == _endpoints.end ()) {
|
||||
errno = ECONNREFUSED;
|
||||
endpoint_t empty = {NULL, options_t ()};
|
||||
return empty;
|
||||
}
|
||||
endpoint_t endpoint = it->second;
|
||||
|
||||
// Increment the command sequence number of the peer so that it won't
|
||||
// get deallocated until "bind" command is issued by the caller.
|
||||
// The subsequent 'bind' has to be called with inc_seqnum parameter
|
||||
// set to false, so that the seqnum isn't incremented twice.
|
||||
endpoint.socket->inc_seqnum ();
|
||||
|
||||
return endpoint;
|
||||
}
|
||||
|
||||
void zmq::ctx_t::pend_connection (const std::string &addr_,
|
||||
const endpoint_t &endpoint_,
|
||||
pipe_t **pipes_)
|
||||
{
|
||||
scoped_lock_t locker (_endpoints_sync);
|
||||
|
||||
const pending_connection_t pending_connection = {endpoint_, pipes_[0],
|
||||
pipes_[1]};
|
||||
|
||||
const endpoints_t::iterator it = _endpoints.find (addr_);
|
||||
if (it == _endpoints.end ()) {
|
||||
// Still no bind.
|
||||
endpoint_.socket->inc_seqnum ();
|
||||
_pending_connections.ZMQ_MAP_INSERT_OR_EMPLACE (addr_,
|
||||
pending_connection);
|
||||
} else {
|
||||
// Bind has happened in the mean time, connect directly
|
||||
connect_inproc_sockets (it->second.socket, it->second.options,
|
||||
pending_connection, connect_side);
|
||||
}
|
||||
}
|
||||
|
||||
void zmq::ctx_t::connect_pending (const char *addr_,
|
||||
zmq::socket_base_t *bind_socket_)
|
||||
{
|
||||
scoped_lock_t locker (_endpoints_sync);
|
||||
|
||||
const std::pair<pending_connections_t::iterator,
|
||||
pending_connections_t::iterator>
|
||||
pending = _pending_connections.equal_range (addr_);
|
||||
for (pending_connections_t::iterator p = pending.first; p != pending.second;
|
||||
++p)
|
||||
connect_inproc_sockets (bind_socket_, _endpoints[addr_].options,
|
||||
p->second, bind_side);
|
||||
|
||||
_pending_connections.erase (pending.first, pending.second);
|
||||
}
|
||||
|
||||
void zmq::ctx_t::connect_inproc_sockets (
|
||||
zmq::socket_base_t *bind_socket_,
|
||||
const options_t &bind_options_,
|
||||
const pending_connection_t &pending_connection_,
|
||||
side side_)
|
||||
{
|
||||
bind_socket_->inc_seqnum ();
|
||||
pending_connection_.bind_pipe->set_tid (bind_socket_->get_tid ());
|
||||
|
||||
if (!bind_options_.recv_routing_id) {
|
||||
msg_t msg;
|
||||
const bool ok = pending_connection_.bind_pipe->read (&msg);
|
||||
zmq_assert (ok);
|
||||
const int rc = msg.close ();
|
||||
errno_assert (rc == 0);
|
||||
}
|
||||
|
||||
if (!get_effective_conflate_option (pending_connection_.endpoint.options)) {
|
||||
pending_connection_.connect_pipe->set_hwms_boost (bind_options_.sndhwm,
|
||||
bind_options_.rcvhwm);
|
||||
pending_connection_.bind_pipe->set_hwms_boost (
|
||||
pending_connection_.endpoint.options.sndhwm,
|
||||
pending_connection_.endpoint.options.rcvhwm);
|
||||
|
||||
pending_connection_.connect_pipe->set_hwms (
|
||||
pending_connection_.endpoint.options.rcvhwm,
|
||||
pending_connection_.endpoint.options.sndhwm);
|
||||
pending_connection_.bind_pipe->set_hwms (bind_options_.rcvhwm,
|
||||
bind_options_.sndhwm);
|
||||
} else {
|
||||
pending_connection_.connect_pipe->set_hwms (-1, -1);
|
||||
pending_connection_.bind_pipe->set_hwms (-1, -1);
|
||||
}
|
||||
|
||||
#ifdef ZMQ_BUILD_DRAFT_API
|
||||
if (bind_options_.can_recv_disconnect_msg
|
||||
&& !bind_options_.disconnect_msg.empty ())
|
||||
pending_connection_.connect_pipe->set_disconnect_msg (
|
||||
bind_options_.disconnect_msg);
|
||||
#endif
|
||||
|
||||
if (side_ == bind_side) {
|
||||
command_t cmd;
|
||||
cmd.type = command_t::bind;
|
||||
cmd.args.bind.pipe = pending_connection_.bind_pipe;
|
||||
bind_socket_->process_command (cmd);
|
||||
bind_socket_->send_inproc_connected (
|
||||
pending_connection_.endpoint.socket);
|
||||
} else
|
||||
pending_connection_.connect_pipe->send_bind (
|
||||
bind_socket_, pending_connection_.bind_pipe, false);
|
||||
|
||||
// When a ctx is terminated all pending inproc connection will be
|
||||
// connected, but the socket will already be closed and the pipe will be
|
||||
// in waiting_for_delimiter state, which means no more writes can be done
|
||||
// and the routing id write fails and causes an assert. Check if the socket
|
||||
// is open before sending.
|
||||
if (pending_connection_.endpoint.options.recv_routing_id
|
||||
&& pending_connection_.endpoint.socket->check_tag ()) {
|
||||
send_routing_id (pending_connection_.bind_pipe, bind_options_);
|
||||
}
|
||||
|
||||
#ifdef ZMQ_BUILD_DRAFT_API
|
||||
// If set, send the hello msg of the bind socket to the pending connection.
|
||||
if (bind_options_.can_send_hello_msg
|
||||
&& bind_options_.hello_msg.size () > 0) {
|
||||
send_hello_msg (pending_connection_.bind_pipe, bind_options_);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef ZMQ_HAVE_VMCI
|
||||
|
||||
int zmq::ctx_t::get_vmci_socket_family ()
|
||||
{
|
||||
zmq::scoped_lock_t locker (_vmci_sync);
|
||||
|
||||
if (_vmci_fd == -1) {
|
||||
_vmci_family = VMCISock_GetAFValueFd (&_vmci_fd);
|
||||
|
||||
if (_vmci_fd != -1) {
|
||||
#ifdef FD_CLOEXEC
|
||||
int rc = fcntl (_vmci_fd, F_SETFD, FD_CLOEXEC);
|
||||
errno_assert (rc != -1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return _vmci_family;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// The last used socket ID, or 0 if no socket was used so far. Note that this
|
||||
// is a global variable. Thus, even sockets created in different contexts have
|
||||
// unique IDs.
|
||||
zmq::atomic_counter_t zmq::ctx_t::max_socket_id;
|
||||
271
3rd/libzmq/src/ctx.hpp
Normal file
271
3rd/libzmq/src/ctx.hpp
Normal file
@@ -0,0 +1,271 @@
|
||||
/*
|
||||
Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ZMQ_CTX_HPP_INCLUDED__
|
||||
#define __ZMQ_CTX_HPP_INCLUDED__
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "mailbox.hpp"
|
||||
#include "array.hpp"
|
||||
#include "config.hpp"
|
||||
#include "mutex.hpp"
|
||||
#include "stdint.hpp"
|
||||
#include "options.hpp"
|
||||
#include "atomic_counter.hpp"
|
||||
#include "thread.hpp"
|
||||
|
||||
namespace zmq
|
||||
{
|
||||
class object_t;
|
||||
class io_thread_t;
|
||||
class socket_base_t;
|
||||
class reaper_t;
|
||||
class pipe_t;
|
||||
|
||||
// Information associated with inproc endpoint. Note that endpoint options
|
||||
// are registered as well so that the peer can access them without a need
|
||||
// for synchronisation, handshaking or similar.
|
||||
struct endpoint_t
|
||||
{
|
||||
socket_base_t *socket;
|
||||
options_t options;
|
||||
};
|
||||
|
||||
class thread_ctx_t
|
||||
{
|
||||
public:
|
||||
thread_ctx_t ();
|
||||
|
||||
// Start a new thread with proper scheduling parameters.
|
||||
void start_thread (thread_t &thread_,
|
||||
thread_fn *tfn_,
|
||||
void *arg_,
|
||||
const char *name_ = NULL) const;
|
||||
|
||||
int set (int option_, const void *optval_, size_t optvallen_);
|
||||
int get (int option_, void *optval_, const size_t *optvallen_);
|
||||
|
||||
protected:
|
||||
// Synchronisation of access to context options.
|
||||
mutex_t _opt_sync;
|
||||
|
||||
private:
|
||||
// Thread parameters.
|
||||
int _thread_priority;
|
||||
int _thread_sched_policy;
|
||||
std::set<int> _thread_affinity_cpus;
|
||||
std::string _thread_name_prefix;
|
||||
};
|
||||
|
||||
// Context object encapsulates all the global state associated with
|
||||
// the library.
|
||||
|
||||
class ctx_t ZMQ_FINAL : public thread_ctx_t
|
||||
{
|
||||
public:
|
||||
// Create the context object.
|
||||
ctx_t ();
|
||||
|
||||
// Returns false if object is not a context.
|
||||
bool check_tag () const;
|
||||
|
||||
// This function is called when user invokes zmq_ctx_term. If there are
|
||||
// no more sockets open it'll cause all the infrastructure to be shut
|
||||
// down. If there are open sockets still, the deallocation happens
|
||||
// after the last one is closed.
|
||||
int terminate ();
|
||||
|
||||
// This function starts the terminate process by unblocking any blocking
|
||||
// operations currently in progress and stopping any more socket activity
|
||||
// (except zmq_close).
|
||||
// This function is non-blocking.
|
||||
// terminate must still be called afterwards.
|
||||
// This function is optional, terminate will unblock any current
|
||||
// operations as well.
|
||||
int shutdown ();
|
||||
|
||||
// Set and get context properties.
|
||||
int set (int option_, const void *optval_, size_t optvallen_);
|
||||
int get (int option_, void *optval_, const size_t *optvallen_);
|
||||
int get (int option_);
|
||||
|
||||
// Create and destroy a socket.
|
||||
zmq::socket_base_t *create_socket (int type_);
|
||||
void destroy_socket (zmq::socket_base_t *socket_);
|
||||
|
||||
// Send command to the destination thread.
|
||||
void send_command (uint32_t tid_, const command_t &command_);
|
||||
|
||||
// Returns the I/O thread that is the least busy at the moment.
|
||||
// Affinity specifies which I/O threads are eligible (0 = all).
|
||||
// Returns NULL if no I/O thread is available.
|
||||
zmq::io_thread_t *choose_io_thread (uint64_t affinity_);
|
||||
|
||||
// Returns reaper thread object.
|
||||
zmq::object_t *get_reaper () const;
|
||||
|
||||
// Management of inproc endpoints.
|
||||
int register_endpoint (const char *addr_, const endpoint_t &endpoint_);
|
||||
int unregister_endpoint (const std::string &addr_,
|
||||
const socket_base_t *socket_);
|
||||
void unregister_endpoints (const zmq::socket_base_t *socket_);
|
||||
endpoint_t find_endpoint (const char *addr_);
|
||||
void pend_connection (const std::string &addr_,
|
||||
const endpoint_t &endpoint_,
|
||||
pipe_t **pipes_);
|
||||
void connect_pending (const char *addr_, zmq::socket_base_t *bind_socket_);
|
||||
|
||||
#ifdef ZMQ_HAVE_VMCI
|
||||
// Return family for the VMCI socket or -1 if it's not available.
|
||||
int get_vmci_socket_family ();
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
term_tid = 0,
|
||||
reaper_tid = 1
|
||||
};
|
||||
|
||||
~ctx_t ();
|
||||
|
||||
bool valid () const;
|
||||
|
||||
private:
|
||||
bool start ();
|
||||
|
||||
struct pending_connection_t
|
||||
{
|
||||
endpoint_t endpoint;
|
||||
pipe_t *connect_pipe;
|
||||
pipe_t *bind_pipe;
|
||||
};
|
||||
|
||||
// Used to check whether the object is a context.
|
||||
uint32_t _tag;
|
||||
|
||||
// Sockets belonging to this context. We need the list so that
|
||||
// we can notify the sockets when zmq_ctx_term() is called.
|
||||
// The sockets will return ETERM then.
|
||||
typedef array_t<socket_base_t> sockets_t;
|
||||
sockets_t _sockets;
|
||||
|
||||
// List of unused thread slots.
|
||||
typedef std::vector<uint32_t> empty_slots_t;
|
||||
empty_slots_t _empty_slots;
|
||||
|
||||
// If true, zmq_init has been called but no socket has been created
|
||||
// yet. Launching of I/O threads is delayed.
|
||||
bool _starting;
|
||||
|
||||
// If true, zmq_ctx_term was already called.
|
||||
bool _terminating;
|
||||
|
||||
// Synchronisation of accesses to global slot-related data:
|
||||
// sockets, empty_slots, terminating. It also synchronises
|
||||
// access to zombie sockets as such (as opposed to slots) and provides
|
||||
// a memory barrier to ensure that all CPU cores see the same data.
|
||||
mutex_t _slot_sync;
|
||||
|
||||
// The reaper thread.
|
||||
zmq::reaper_t *_reaper;
|
||||
|
||||
// I/O threads.
|
||||
typedef std::vector<zmq::io_thread_t *> io_threads_t;
|
||||
io_threads_t _io_threads;
|
||||
|
||||
// Array of pointers to mailboxes for both application and I/O threads.
|
||||
std::vector<i_mailbox *> _slots;
|
||||
|
||||
// Mailbox for zmq_ctx_term thread.
|
||||
mailbox_t _term_mailbox;
|
||||
|
||||
// List of inproc endpoints within this context.
|
||||
typedef std::map<std::string, endpoint_t> endpoints_t;
|
||||
endpoints_t _endpoints;
|
||||
|
||||
// List of inproc connection endpoints pending a bind
|
||||
typedef std::multimap<std::string, pending_connection_t>
|
||||
pending_connections_t;
|
||||
pending_connections_t _pending_connections;
|
||||
|
||||
// Synchronisation of access to the list of inproc endpoints.
|
||||
mutex_t _endpoints_sync;
|
||||
|
||||
// Maximum socket ID.
|
||||
static atomic_counter_t max_socket_id;
|
||||
|
||||
// Maximum number of sockets that can be opened at the same time.
|
||||
int _max_sockets;
|
||||
|
||||
// Maximum allowed message size
|
||||
int _max_msgsz;
|
||||
|
||||
// Number of I/O threads to launch.
|
||||
int _io_thread_count;
|
||||
|
||||
// Does context wait (possibly forever) on termination?
|
||||
bool _blocky;
|
||||
|
||||
// Is IPv6 enabled on this context?
|
||||
bool _ipv6;
|
||||
|
||||
// Should we use zero copy message decoding in this context?
|
||||
bool _zero_copy;
|
||||
|
||||
ZMQ_NON_COPYABLE_NOR_MOVABLE (ctx_t)
|
||||
|
||||
#ifdef HAVE_FORK
|
||||
// the process that created this context. Used to detect forking.
|
||||
pid_t _pid;
|
||||
#endif
|
||||
enum side
|
||||
{
|
||||
connect_side,
|
||||
bind_side
|
||||
};
|
||||
|
||||
static void
|
||||
connect_inproc_sockets (zmq::socket_base_t *bind_socket_,
|
||||
const options_t &bind_options_,
|
||||
const pending_connection_t &pending_connection_,
|
||||
side side_);
|
||||
|
||||
#ifdef ZMQ_HAVE_VMCI
|
||||
int _vmci_fd;
|
||||
int _vmci_family;
|
||||
mutex_t _vmci_sync;
|
||||
#endif
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
287
3rd/libzmq/src/curve_client.cpp
Normal file
287
3rd/libzmq/src/curve_client.cpp
Normal file
@@ -0,0 +1,287 @@
|
||||
/*
|
||||
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "macros.hpp"
|
||||
|
||||
#ifdef ZMQ_HAVE_CURVE
|
||||
|
||||
#include "msg.hpp"
|
||||
#include "session_base.hpp"
|
||||
#include "err.hpp"
|
||||
#include "curve_client.hpp"
|
||||
#include "wire.hpp"
|
||||
#include "curve_client_tools.hpp"
|
||||
#include "secure_allocator.hpp"
|
||||
|
||||
zmq::curve_client_t::curve_client_t (session_base_t *session_,
|
||||
const options_t &options_,
|
||||
const bool downgrade_sub_) :
|
||||
mechanism_base_t (session_, options_),
|
||||
curve_mechanism_base_t (session_,
|
||||
options_,
|
||||
"CurveZMQMESSAGEC",
|
||||
"CurveZMQMESSAGES",
|
||||
downgrade_sub_),
|
||||
_state (send_hello),
|
||||
_tools (options_.curve_public_key,
|
||||
options_.curve_secret_key,
|
||||
options_.curve_server_key)
|
||||
{
|
||||
}
|
||||
|
||||
zmq::curve_client_t::~curve_client_t ()
|
||||
{
|
||||
}
|
||||
|
||||
int zmq::curve_client_t::next_handshake_command (msg_t *msg_)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
switch (_state) {
|
||||
case send_hello:
|
||||
rc = produce_hello (msg_);
|
||||
if (rc == 0)
|
||||
_state = expect_welcome;
|
||||
break;
|
||||
case send_initiate:
|
||||
rc = produce_initiate (msg_);
|
||||
if (rc == 0)
|
||||
_state = expect_ready;
|
||||
break;
|
||||
default:
|
||||
errno = EAGAIN;
|
||||
rc = -1;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int zmq::curve_client_t::process_handshake_command (msg_t *msg_)
|
||||
{
|
||||
const unsigned char *msg_data =
|
||||
static_cast<unsigned char *> (msg_->data ());
|
||||
const size_t msg_size = msg_->size ();
|
||||
|
||||
int rc = 0;
|
||||
if (curve_client_tools_t::is_handshake_command_welcome (msg_data, msg_size))
|
||||
rc = process_welcome (msg_data, msg_size);
|
||||
else if (curve_client_tools_t::is_handshake_command_ready (msg_data,
|
||||
msg_size))
|
||||
rc = process_ready (msg_data, msg_size);
|
||||
else if (curve_client_tools_t::is_handshake_command_error (msg_data,
|
||||
msg_size))
|
||||
rc = process_error (msg_data, msg_size);
|
||||
else {
|
||||
session->get_socket ()->event_handshake_failed_protocol (
|
||||
session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZMTP_UNEXPECTED_COMMAND);
|
||||
errno = EPROTO;
|
||||
rc = -1;
|
||||
}
|
||||
|
||||
if (rc == 0) {
|
||||
rc = msg_->close ();
|
||||
errno_assert (rc == 0);
|
||||
rc = msg_->init ();
|
||||
errno_assert (rc == 0);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int zmq::curve_client_t::encode (msg_t *msg_)
|
||||
{
|
||||
zmq_assert (_state == connected);
|
||||
return curve_mechanism_base_t::encode (msg_);
|
||||
}
|
||||
|
||||
int zmq::curve_client_t::decode (msg_t *msg_)
|
||||
{
|
||||
zmq_assert (_state == connected);
|
||||
return curve_mechanism_base_t::decode (msg_);
|
||||
}
|
||||
|
||||
zmq::mechanism_t::status_t zmq::curve_client_t::status () const
|
||||
{
|
||||
if (_state == connected)
|
||||
return mechanism_t::ready;
|
||||
if (_state == error_received)
|
||||
return mechanism_t::error;
|
||||
|
||||
return mechanism_t::handshaking;
|
||||
}
|
||||
|
||||
int zmq::curve_client_t::produce_hello (msg_t *msg_)
|
||||
{
|
||||
int rc = msg_->init_size (200);
|
||||
errno_assert (rc == 0);
|
||||
|
||||
rc = _tools.produce_hello (msg_->data (), get_and_inc_nonce ());
|
||||
if (rc == -1) {
|
||||
session->get_socket ()->event_handshake_failed_protocol (
|
||||
session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZMTP_CRYPTOGRAPHIC);
|
||||
|
||||
// TODO this is somewhat inconsistent: we call init_size, but we may
|
||||
// not close msg_; i.e. we assume that msg_ is initialized but empty
|
||||
// (if it were non-empty, calling init_size might cause a leak!)
|
||||
|
||||
// msg_->close ();
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int zmq::curve_client_t::process_welcome (const uint8_t *msg_data_,
|
||||
size_t msg_size_)
|
||||
{
|
||||
const int rc = _tools.process_welcome (msg_data_, msg_size_,
|
||||
get_writable_precom_buffer ());
|
||||
|
||||
if (rc == -1) {
|
||||
session->get_socket ()->event_handshake_failed_protocol (
|
||||
session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZMTP_CRYPTOGRAPHIC);
|
||||
|
||||
errno = EPROTO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
_state = send_initiate;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int zmq::curve_client_t::produce_initiate (msg_t *msg_)
|
||||
{
|
||||
const size_t metadata_length = basic_properties_len ();
|
||||
std::vector<unsigned char, secure_allocator_t<unsigned char> >
|
||||
metadata_plaintext (metadata_length);
|
||||
|
||||
add_basic_properties (&metadata_plaintext[0], metadata_length);
|
||||
|
||||
const size_t msg_size =
|
||||
113 + 128 + crypto_box_BOXZEROBYTES + metadata_length;
|
||||
int rc = msg_->init_size (msg_size);
|
||||
errno_assert (rc == 0);
|
||||
|
||||
rc = _tools.produce_initiate (msg_->data (), msg_size, get_and_inc_nonce (),
|
||||
&metadata_plaintext[0], metadata_length);
|
||||
|
||||
if (-1 == rc) {
|
||||
session->get_socket ()->event_handshake_failed_protocol (
|
||||
session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZMTP_CRYPTOGRAPHIC);
|
||||
|
||||
// TODO see comment in produce_hello
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int zmq::curve_client_t::process_ready (const uint8_t *msg_data_,
|
||||
size_t msg_size_)
|
||||
{
|
||||
if (msg_size_ < 30) {
|
||||
session->get_socket ()->event_handshake_failed_protocol (
|
||||
session->get_endpoint (),
|
||||
ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_READY);
|
||||
errno = EPROTO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
const size_t clen = (msg_size_ - 14) + crypto_box_BOXZEROBYTES;
|
||||
|
||||
uint8_t ready_nonce[crypto_box_NONCEBYTES];
|
||||
std::vector<uint8_t, secure_allocator_t<uint8_t> > ready_plaintext (
|
||||
crypto_box_ZEROBYTES + clen);
|
||||
std::vector<uint8_t> ready_box (crypto_box_BOXZEROBYTES + 16 + clen);
|
||||
|
||||
std::fill (ready_box.begin (), ready_box.begin () + crypto_box_BOXZEROBYTES,
|
||||
0);
|
||||
memcpy (&ready_box[crypto_box_BOXZEROBYTES], msg_data_ + 14,
|
||||
clen - crypto_box_BOXZEROBYTES);
|
||||
|
||||
memcpy (ready_nonce, "CurveZMQREADY---", 16);
|
||||
memcpy (ready_nonce + 16, msg_data_ + 6, 8);
|
||||
set_peer_nonce (get_uint64 (msg_data_ + 6));
|
||||
|
||||
int rc = crypto_box_open_afternm (&ready_plaintext[0], &ready_box[0], clen,
|
||||
ready_nonce, get_precom_buffer ());
|
||||
|
||||
if (rc != 0) {
|
||||
session->get_socket ()->event_handshake_failed_protocol (
|
||||
session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZMTP_CRYPTOGRAPHIC);
|
||||
errno = EPROTO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = parse_metadata (&ready_plaintext[crypto_box_ZEROBYTES],
|
||||
clen - crypto_box_ZEROBYTES);
|
||||
|
||||
if (rc == 0)
|
||||
_state = connected;
|
||||
else {
|
||||
session->get_socket ()->event_handshake_failed_protocol (
|
||||
session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZMTP_INVALID_METADATA);
|
||||
errno = EPROTO;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int zmq::curve_client_t::process_error (const uint8_t *msg_data_,
|
||||
size_t msg_size_)
|
||||
{
|
||||
if (_state != expect_welcome && _state != expect_ready) {
|
||||
session->get_socket ()->event_handshake_failed_protocol (
|
||||
session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZMTP_UNEXPECTED_COMMAND);
|
||||
errno = EPROTO;
|
||||
return -1;
|
||||
}
|
||||
if (msg_size_ < 7) {
|
||||
session->get_socket ()->event_handshake_failed_protocol (
|
||||
session->get_endpoint (),
|
||||
ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_ERROR);
|
||||
errno = EPROTO;
|
||||
return -1;
|
||||
}
|
||||
const size_t error_reason_len = static_cast<size_t> (msg_data_[6]);
|
||||
if (error_reason_len > msg_size_ - 7) {
|
||||
session->get_socket ()->event_handshake_failed_protocol (
|
||||
session->get_endpoint (),
|
||||
ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_ERROR);
|
||||
errno = EPROTO;
|
||||
return -1;
|
||||
}
|
||||
const char *error_reason = reinterpret_cast<const char *> (msg_data_) + 7;
|
||||
handle_error_reason (error_reason, error_reason_len);
|
||||
_state = error_received;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
86
3rd/libzmq/src/curve_client.hpp
Normal file
86
3rd/libzmq/src/curve_client.hpp
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ZMQ_CURVE_CLIENT_HPP_INCLUDED__
|
||||
#define __ZMQ_CURVE_CLIENT_HPP_INCLUDED__
|
||||
|
||||
#ifdef ZMQ_HAVE_CURVE
|
||||
|
||||
#include "curve_mechanism_base.hpp"
|
||||
#include "options.hpp"
|
||||
#include "curve_client_tools.hpp"
|
||||
|
||||
namespace zmq
|
||||
{
|
||||
class msg_t;
|
||||
class session_base_t;
|
||||
|
||||
class curve_client_t ZMQ_FINAL : public curve_mechanism_base_t
|
||||
{
|
||||
public:
|
||||
curve_client_t (session_base_t *session_,
|
||||
const options_t &options_,
|
||||
const bool downgrade_sub_);
|
||||
~curve_client_t () ZMQ_FINAL;
|
||||
|
||||
// mechanism implementation
|
||||
int next_handshake_command (msg_t *msg_) ZMQ_FINAL;
|
||||
int process_handshake_command (msg_t *msg_) ZMQ_FINAL;
|
||||
int encode (msg_t *msg_) ZMQ_FINAL;
|
||||
int decode (msg_t *msg_) ZMQ_FINAL;
|
||||
status_t status () const ZMQ_FINAL;
|
||||
|
||||
private:
|
||||
enum state_t
|
||||
{
|
||||
send_hello,
|
||||
expect_welcome,
|
||||
send_initiate,
|
||||
expect_ready,
|
||||
error_received,
|
||||
connected
|
||||
};
|
||||
|
||||
// Current FSM state
|
||||
state_t _state;
|
||||
|
||||
// CURVE protocol tools
|
||||
curve_client_tools_t _tools;
|
||||
|
||||
int produce_hello (msg_t *msg_);
|
||||
int process_welcome (const uint8_t *msg_data_, size_t msg_size_);
|
||||
int produce_initiate (msg_t *msg_);
|
||||
int process_ready (const uint8_t *msg_data_, size_t msg_size_);
|
||||
int process_error (const uint8_t *msg_data_, size_t msg_size_);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
316
3rd/libzmq/src/curve_client_tools.hpp
Normal file
316
3rd/libzmq/src/curve_client_tools.hpp
Normal file
@@ -0,0 +1,316 @@
|
||||
/*
|
||||
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ZMQ_CURVE_CLIENT_TOOLS_HPP_INCLUDED__
|
||||
#define __ZMQ_CURVE_CLIENT_TOOLS_HPP_INCLUDED__
|
||||
|
||||
#ifdef ZMQ_HAVE_CURVE
|
||||
|
||||
#if defined(ZMQ_USE_TWEETNACL)
|
||||
#include "tweetnacl.h"
|
||||
#elif defined(ZMQ_USE_LIBSODIUM)
|
||||
#include "sodium.h"
|
||||
#endif
|
||||
|
||||
#if crypto_box_NONCEBYTES != 24 || crypto_box_PUBLICKEYBYTES != 32 \
|
||||
|| crypto_box_SECRETKEYBYTES != 32 || crypto_box_ZEROBYTES != 32 \
|
||||
|| crypto_box_BOXZEROBYTES != 16
|
||||
#error "CURVE library not built properly"
|
||||
#endif
|
||||
|
||||
#include "wire.hpp"
|
||||
#include "err.hpp"
|
||||
#include "secure_allocator.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace zmq
|
||||
{
|
||||
struct curve_client_tools_t
|
||||
{
|
||||
static int produce_hello (void *data_,
|
||||
const uint8_t *server_key_,
|
||||
const uint64_t cn_nonce_,
|
||||
const uint8_t *cn_public_,
|
||||
const uint8_t *cn_secret_)
|
||||
{
|
||||
uint8_t hello_nonce[crypto_box_NONCEBYTES];
|
||||
std::vector<uint8_t, secure_allocator_t<uint8_t> > hello_plaintext (
|
||||
crypto_box_ZEROBYTES + 64, 0);
|
||||
uint8_t hello_box[crypto_box_BOXZEROBYTES + 80];
|
||||
|
||||
// Prepare the full nonce
|
||||
memcpy (hello_nonce, "CurveZMQHELLO---", 16);
|
||||
put_uint64 (hello_nonce + 16, cn_nonce_);
|
||||
|
||||
// Create Box [64 * %x0](C'->S)
|
||||
const int rc =
|
||||
crypto_box (hello_box, &hello_plaintext[0], hello_plaintext.size (),
|
||||
hello_nonce, server_key_, cn_secret_);
|
||||
if (rc == -1)
|
||||
return -1;
|
||||
|
||||
uint8_t *hello = static_cast<uint8_t *> (data_);
|
||||
|
||||
memcpy (hello, "\x05HELLO", 6);
|
||||
// CurveZMQ major and minor version numbers
|
||||
memcpy (hello + 6, "\1\0", 2);
|
||||
// Anti-amplification padding
|
||||
memset (hello + 8, 0, 72);
|
||||
// Client public connection key
|
||||
memcpy (hello + 80, cn_public_, crypto_box_PUBLICKEYBYTES);
|
||||
// Short nonce, prefixed by "CurveZMQHELLO---"
|
||||
memcpy (hello + 112, hello_nonce + 16, 8);
|
||||
// Signature, Box [64 * %x0](C'->S)
|
||||
memcpy (hello + 120, hello_box + crypto_box_BOXZEROBYTES, 80);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int process_welcome (const uint8_t *msg_data_,
|
||||
size_t msg_size_,
|
||||
const uint8_t *server_key_,
|
||||
const uint8_t *cn_secret_,
|
||||
uint8_t *cn_server_,
|
||||
uint8_t *cn_cookie_,
|
||||
uint8_t *cn_precom_)
|
||||
{
|
||||
if (msg_size_ != 168) {
|
||||
errno = EPROTO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t welcome_nonce[crypto_box_NONCEBYTES];
|
||||
std::vector<uint8_t, secure_allocator_t<uint8_t> > welcome_plaintext (
|
||||
crypto_box_ZEROBYTES + 128);
|
||||
uint8_t welcome_box[crypto_box_BOXZEROBYTES + 144];
|
||||
|
||||
// Open Box [S' + cookie](C'->S)
|
||||
memset (welcome_box, 0, crypto_box_BOXZEROBYTES);
|
||||
memcpy (welcome_box + crypto_box_BOXZEROBYTES, msg_data_ + 24, 144);
|
||||
|
||||
memcpy (welcome_nonce, "WELCOME-", 8);
|
||||
memcpy (welcome_nonce + 8, msg_data_ + 8, 16);
|
||||
|
||||
int rc = crypto_box_open (&welcome_plaintext[0], welcome_box,
|
||||
sizeof welcome_box, welcome_nonce,
|
||||
server_key_, cn_secret_);
|
||||
if (rc != 0) {
|
||||
errno = EPROTO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy (cn_server_, &welcome_plaintext[crypto_box_ZEROBYTES], 32);
|
||||
memcpy (cn_cookie_, &welcome_plaintext[crypto_box_ZEROBYTES + 32],
|
||||
16 + 80);
|
||||
|
||||
// Message independent precomputation
|
||||
rc = crypto_box_beforenm (cn_precom_, cn_server_, cn_secret_);
|
||||
zmq_assert (rc == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int produce_initiate (void *data_,
|
||||
size_t size_,
|
||||
const uint64_t cn_nonce_,
|
||||
const uint8_t *server_key_,
|
||||
const uint8_t *public_key_,
|
||||
const uint8_t *secret_key_,
|
||||
const uint8_t *cn_public_,
|
||||
const uint8_t *cn_secret_,
|
||||
const uint8_t *cn_server_,
|
||||
const uint8_t *cn_cookie_,
|
||||
const uint8_t *metadata_plaintext_,
|
||||
const size_t metadata_length_)
|
||||
{
|
||||
uint8_t vouch_nonce[crypto_box_NONCEBYTES];
|
||||
std::vector<uint8_t, secure_allocator_t<uint8_t> > vouch_plaintext (
|
||||
crypto_box_ZEROBYTES + 64);
|
||||
uint8_t vouch_box[crypto_box_BOXZEROBYTES + 80];
|
||||
|
||||
// Create vouch = Box [C',S](C->S')
|
||||
std::fill (vouch_plaintext.begin (),
|
||||
vouch_plaintext.begin () + crypto_box_ZEROBYTES, 0);
|
||||
memcpy (&vouch_plaintext[crypto_box_ZEROBYTES], cn_public_, 32);
|
||||
memcpy (&vouch_plaintext[crypto_box_ZEROBYTES + 32], server_key_, 32);
|
||||
|
||||
memset (vouch_nonce, 0, crypto_box_NONCEBYTES);
|
||||
memcpy (vouch_nonce, "VOUCH---", 8);
|
||||
randombytes (vouch_nonce + 8, 16);
|
||||
|
||||
int rc =
|
||||
crypto_box (vouch_box, &vouch_plaintext[0], vouch_plaintext.size (),
|
||||
vouch_nonce, cn_server_, secret_key_);
|
||||
if (rc == -1)
|
||||
return -1;
|
||||
|
||||
uint8_t initiate_nonce[crypto_box_NONCEBYTES];
|
||||
std::vector<uint8_t> initiate_box (crypto_box_BOXZEROBYTES + 144
|
||||
+ metadata_length_);
|
||||
std::vector<uint8_t, secure_allocator_t<uint8_t> > initiate_plaintext (
|
||||
crypto_box_ZEROBYTES + 128 + metadata_length_);
|
||||
|
||||
// Create Box [C + vouch + metadata](C'->S')
|
||||
std::fill (initiate_plaintext.begin (),
|
||||
initiate_plaintext.begin () + crypto_box_ZEROBYTES, 0);
|
||||
memcpy (&initiate_plaintext[crypto_box_ZEROBYTES], public_key_, 32);
|
||||
memcpy (&initiate_plaintext[crypto_box_ZEROBYTES + 32], vouch_nonce + 8,
|
||||
16);
|
||||
memcpy (&initiate_plaintext[crypto_box_ZEROBYTES + 48],
|
||||
vouch_box + crypto_box_BOXZEROBYTES, 80);
|
||||
if (metadata_length_) {
|
||||
memcpy (&initiate_plaintext[crypto_box_ZEROBYTES + 48 + 80],
|
||||
metadata_plaintext_, metadata_length_);
|
||||
}
|
||||
|
||||
memcpy (initiate_nonce, "CurveZMQINITIATE", 16);
|
||||
put_uint64 (initiate_nonce + 16, cn_nonce_);
|
||||
|
||||
rc = crypto_box (&initiate_box[0], &initiate_plaintext[0],
|
||||
crypto_box_ZEROBYTES + 128 + metadata_length_,
|
||||
initiate_nonce, cn_server_, cn_secret_);
|
||||
|
||||
if (rc == -1)
|
||||
return -1;
|
||||
|
||||
uint8_t *initiate = static_cast<uint8_t *> (data_);
|
||||
|
||||
zmq_assert (size_
|
||||
== 113 + 128 + crypto_box_BOXZEROBYTES + metadata_length_);
|
||||
|
||||
memcpy (initiate, "\x08INITIATE", 9);
|
||||
// Cookie provided by the server in the WELCOME command
|
||||
memcpy (initiate + 9, cn_cookie_, 96);
|
||||
// Short nonce, prefixed by "CurveZMQINITIATE"
|
||||
memcpy (initiate + 105, initiate_nonce + 16, 8);
|
||||
// Box [C + vouch + metadata](C'->S')
|
||||
memcpy (initiate + 113, &initiate_box[crypto_box_BOXZEROBYTES],
|
||||
128 + metadata_length_ + crypto_box_BOXZEROBYTES);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool is_handshake_command_welcome (const uint8_t *msg_data_,
|
||||
const size_t msg_size_)
|
||||
{
|
||||
return is_handshake_command (msg_data_, msg_size_, "\7WELCOME");
|
||||
}
|
||||
|
||||
static bool is_handshake_command_ready (const uint8_t *msg_data_,
|
||||
const size_t msg_size_)
|
||||
{
|
||||
return is_handshake_command (msg_data_, msg_size_, "\5READY");
|
||||
}
|
||||
|
||||
static bool is_handshake_command_error (const uint8_t *msg_data_,
|
||||
const size_t msg_size_)
|
||||
{
|
||||
return is_handshake_command (msg_data_, msg_size_, "\5ERROR");
|
||||
}
|
||||
|
||||
// non-static functions
|
||||
curve_client_tools_t (
|
||||
const uint8_t (&curve_public_key_)[crypto_box_PUBLICKEYBYTES],
|
||||
const uint8_t (&curve_secret_key_)[crypto_box_SECRETKEYBYTES],
|
||||
const uint8_t (&curve_server_key_)[crypto_box_PUBLICKEYBYTES])
|
||||
{
|
||||
int rc;
|
||||
memcpy (public_key, curve_public_key_, crypto_box_PUBLICKEYBYTES);
|
||||
memcpy (secret_key, curve_secret_key_, crypto_box_SECRETKEYBYTES);
|
||||
memcpy (server_key, curve_server_key_, crypto_box_PUBLICKEYBYTES);
|
||||
|
||||
// Generate short-term key pair
|
||||
memset (cn_secret, 0, crypto_box_SECRETKEYBYTES);
|
||||
memset (cn_public, 0, crypto_box_PUBLICKEYBYTES);
|
||||
rc = crypto_box_keypair (cn_public, cn_secret);
|
||||
zmq_assert (rc == 0);
|
||||
}
|
||||
|
||||
int produce_hello (void *data_, const uint64_t cn_nonce_) const
|
||||
{
|
||||
return produce_hello (data_, server_key, cn_nonce_, cn_public,
|
||||
cn_secret);
|
||||
}
|
||||
|
||||
int process_welcome (const uint8_t *msg_data_,
|
||||
size_t msg_size_,
|
||||
uint8_t *cn_precom_)
|
||||
{
|
||||
return process_welcome (msg_data_, msg_size_, server_key, cn_secret,
|
||||
cn_server, cn_cookie, cn_precom_);
|
||||
}
|
||||
|
||||
int produce_initiate (void *data_,
|
||||
size_t size_,
|
||||
const uint64_t cn_nonce_,
|
||||
const uint8_t *metadata_plaintext_,
|
||||
const size_t metadata_length_) const
|
||||
{
|
||||
return produce_initiate (data_, size_, cn_nonce_, server_key,
|
||||
public_key, secret_key, cn_public, cn_secret,
|
||||
cn_server, cn_cookie, metadata_plaintext_,
|
||||
metadata_length_);
|
||||
}
|
||||
|
||||
// Our public key (C)
|
||||
uint8_t public_key[crypto_box_PUBLICKEYBYTES];
|
||||
|
||||
// Our secret key (c)
|
||||
uint8_t secret_key[crypto_box_SECRETKEYBYTES];
|
||||
|
||||
// Our short-term public key (C')
|
||||
uint8_t cn_public[crypto_box_PUBLICKEYBYTES];
|
||||
|
||||
// Our short-term secret key (c')
|
||||
uint8_t cn_secret[crypto_box_SECRETKEYBYTES];
|
||||
|
||||
// Server's public key (S)
|
||||
uint8_t server_key[crypto_box_PUBLICKEYBYTES];
|
||||
|
||||
// Server's short-term public key (S')
|
||||
uint8_t cn_server[crypto_box_PUBLICKEYBYTES];
|
||||
|
||||
// Cookie received from server
|
||||
uint8_t cn_cookie[16 + 80];
|
||||
|
||||
private:
|
||||
template <size_t N>
|
||||
static bool is_handshake_command (const uint8_t *msg_data_,
|
||||
const size_t msg_size_,
|
||||
const char (&prefix_)[N])
|
||||
{
|
||||
return msg_size_ >= (N - 1) && !memcmp (msg_data_, prefix_, N - 1);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
313
3rd/libzmq/src/curve_mechanism_base.cpp
Normal file
313
3rd/libzmq/src/curve_mechanism_base.cpp
Normal file
@@ -0,0 +1,313 @@
|
||||
/*
|
||||
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "curve_mechanism_base.hpp"
|
||||
#include "msg.hpp"
|
||||
#include "wire.hpp"
|
||||
#include "session_base.hpp"
|
||||
|
||||
#ifdef ZMQ_HAVE_CURVE
|
||||
|
||||
#ifdef ZMQ_USE_LIBSODIUM
|
||||
// libsodium added crypto_box_easy_afternm and crypto_box_open_easy_afternm with
|
||||
// https: //github.com/jedisct1/libsodium/commit/aaf5fbf2e53a33b18d8ea9bdf2c6f73d7acc8c3e
|
||||
#if SODIUM_LIBRARY_VERSION_MAJOR > 7 \
|
||||
|| (SODIUM_LIBRARY_VERSION_MAJOR == 7 && SODIUM_LIBRARY_VERSION_MINOR >= 4)
|
||||
#define ZMQ_HAVE_CRYPTO_BOX_EASY_FNS 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
zmq::curve_mechanism_base_t::curve_mechanism_base_t (
|
||||
session_base_t *session_,
|
||||
const options_t &options_,
|
||||
const char *encode_nonce_prefix_,
|
||||
const char *decode_nonce_prefix_,
|
||||
const bool downgrade_sub_) :
|
||||
mechanism_base_t (session_, options_),
|
||||
curve_encoding_t (
|
||||
encode_nonce_prefix_, decode_nonce_prefix_, downgrade_sub_)
|
||||
{
|
||||
}
|
||||
|
||||
int zmq::curve_mechanism_base_t::encode (msg_t *msg_)
|
||||
{
|
||||
return curve_encoding_t::encode (msg_);
|
||||
}
|
||||
|
||||
int zmq::curve_mechanism_base_t::decode (msg_t *msg_)
|
||||
{
|
||||
int rc = check_basic_command_structure (msg_);
|
||||
if (rc == -1)
|
||||
return -1;
|
||||
|
||||
int error_event_code;
|
||||
rc = curve_encoding_t::decode (msg_, &error_event_code);
|
||||
if (-1 == rc) {
|
||||
session->get_socket ()->event_handshake_failed_protocol (
|
||||
session->get_endpoint (), error_event_code);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
zmq::curve_encoding_t::curve_encoding_t (const char *encode_nonce_prefix_,
|
||||
const char *decode_nonce_prefix_,
|
||||
const bool downgrade_sub_) :
|
||||
_encode_nonce_prefix (encode_nonce_prefix_),
|
||||
_decode_nonce_prefix (decode_nonce_prefix_),
|
||||
_cn_nonce (1),
|
||||
_cn_peer_nonce (1),
|
||||
_downgrade_sub (downgrade_sub_)
|
||||
{
|
||||
}
|
||||
|
||||
// Right now, we only transport the lower two bit flags of zmq::msg_t, so they
|
||||
// are binary identical, and we can just use a bitmask to select them. If we
|
||||
// happened to add more flags, this might change.
|
||||
static const uint8_t flag_mask = zmq::msg_t::more | zmq::msg_t::command;
|
||||
static const size_t flags_len = 1;
|
||||
static const size_t nonce_prefix_len = 16;
|
||||
static const char message_command[] = "\x07MESSAGE";
|
||||
static const size_t message_command_len = sizeof (message_command) - 1;
|
||||
static const size_t message_header_len =
|
||||
message_command_len + sizeof (zmq::curve_encoding_t::nonce_t);
|
||||
|
||||
#ifndef ZMQ_USE_LIBSODIUM
|
||||
static const size_t crypto_box_MACBYTES = 16;
|
||||
#endif
|
||||
|
||||
int zmq::curve_encoding_t::check_validity (msg_t *msg_, int *error_event_code_)
|
||||
{
|
||||
const size_t size = msg_->size ();
|
||||
const uint8_t *const message = static_cast<uint8_t *> (msg_->data ());
|
||||
|
||||
if (size < message_command_len
|
||||
|| 0 != memcmp (message, message_command, message_command_len)) {
|
||||
*error_event_code_ = ZMQ_PROTOCOL_ERROR_ZMTP_UNEXPECTED_COMMAND;
|
||||
errno = EPROTO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (size < message_header_len + crypto_box_MACBYTES + flags_len) {
|
||||
*error_event_code_ = ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_MESSAGE;
|
||||
errno = EPROTO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
{
|
||||
const uint64_t nonce = get_uint64 (message + message_command_len);
|
||||
if (nonce <= _cn_peer_nonce) {
|
||||
*error_event_code_ = ZMQ_PROTOCOL_ERROR_ZMTP_INVALID_SEQUENCE;
|
||||
errno = EPROTO;
|
||||
return -1;
|
||||
}
|
||||
set_peer_nonce (nonce);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int zmq::curve_encoding_t::encode (msg_t *msg_)
|
||||
{
|
||||
size_t sub_cancel_len = 0;
|
||||
uint8_t message_nonce[crypto_box_NONCEBYTES];
|
||||
memcpy (message_nonce, _encode_nonce_prefix, nonce_prefix_len);
|
||||
put_uint64 (message_nonce + nonce_prefix_len, get_and_inc_nonce ());
|
||||
|
||||
if (msg_->is_subscribe () || msg_->is_cancel ()) {
|
||||
if (_downgrade_sub)
|
||||
sub_cancel_len = 1;
|
||||
else
|
||||
sub_cancel_len = msg_->is_cancel ()
|
||||
? zmq::msg_t::cancel_cmd_name_size
|
||||
: zmq::msg_t::sub_cmd_name_size;
|
||||
}
|
||||
|
||||
#ifdef ZMQ_HAVE_CRYPTO_BOX_EASY_FNS
|
||||
const size_t mlen = flags_len + sub_cancel_len + msg_->size ();
|
||||
std::vector<uint8_t> message_plaintext (mlen);
|
||||
#else
|
||||
const size_t mlen =
|
||||
crypto_box_ZEROBYTES + flags_len + sub_cancel_len + msg_->size ();
|
||||
std::vector<uint8_t> message_plaintext_with_zerobytes (mlen);
|
||||
uint8_t *const message_plaintext =
|
||||
&message_plaintext_with_zerobytes[crypto_box_ZEROBYTES];
|
||||
|
||||
std::fill (message_plaintext_with_zerobytes.begin (),
|
||||
message_plaintext_with_zerobytes.begin () + crypto_box_ZEROBYTES,
|
||||
0);
|
||||
#endif
|
||||
|
||||
const uint8_t flags = msg_->flags () & flag_mask;
|
||||
message_plaintext[0] = flags;
|
||||
|
||||
// For backward compatibility subscribe/cancel command messages are not stored with
|
||||
// the message flags, and are encoded in the encoder, so that messages for < 3.0 peers
|
||||
// can be encoded in the "old" 0/1 way rather than as commands.
|
||||
if (sub_cancel_len == 1)
|
||||
message_plaintext[flags_len] = msg_->is_subscribe () ? 1 : 0;
|
||||
else if (sub_cancel_len == zmq::msg_t::sub_cmd_name_size) {
|
||||
message_plaintext[0] |= zmq::msg_t::command;
|
||||
memcpy (&message_plaintext[flags_len], zmq::sub_cmd_name,
|
||||
zmq::msg_t::sub_cmd_name_size);
|
||||
} else if (sub_cancel_len == zmq::msg_t::cancel_cmd_name_size) {
|
||||
message_plaintext[0] |= zmq::msg_t::command;
|
||||
memcpy (&message_plaintext[flags_len], zmq::cancel_cmd_name,
|
||||
zmq::msg_t::cancel_cmd_name_size);
|
||||
}
|
||||
|
||||
// this is copying the data from insecure memory, so there is no point in
|
||||
// using secure_allocator_t for message_plaintext
|
||||
if (msg_->size () > 0)
|
||||
memcpy (&message_plaintext[flags_len + sub_cancel_len], msg_->data (),
|
||||
msg_->size ());
|
||||
|
||||
#ifdef ZMQ_HAVE_CRYPTO_BOX_EASY_FNS
|
||||
msg_t msg_box;
|
||||
int rc =
|
||||
msg_box.init_size (message_header_len + mlen + crypto_box_MACBYTES);
|
||||
zmq_assert (rc == 0);
|
||||
|
||||
rc = crypto_box_easy_afternm (
|
||||
static_cast<uint8_t *> (msg_box.data ()) + message_header_len,
|
||||
&message_plaintext[0], mlen, message_nonce, _cn_precom);
|
||||
zmq_assert (rc == 0);
|
||||
|
||||
msg_->move (msg_box);
|
||||
|
||||
uint8_t *const message = static_cast<uint8_t *> (msg_->data ());
|
||||
#else
|
||||
std::vector<uint8_t> message_box (mlen);
|
||||
|
||||
int rc =
|
||||
crypto_box_afternm (&message_box[0], &message_plaintext_with_zerobytes[0],
|
||||
mlen, message_nonce, _cn_precom);
|
||||
zmq_assert (rc == 0);
|
||||
|
||||
rc = msg_->close ();
|
||||
zmq_assert (rc == 0);
|
||||
|
||||
rc = msg_->init_size (16 + mlen - crypto_box_BOXZEROBYTES);
|
||||
zmq_assert (rc == 0);
|
||||
|
||||
uint8_t *const message = static_cast<uint8_t *> (msg_->data ());
|
||||
|
||||
memcpy (message + message_header_len, &message_box[crypto_box_BOXZEROBYTES],
|
||||
mlen - crypto_box_BOXZEROBYTES);
|
||||
#endif
|
||||
|
||||
memcpy (message, message_command, message_command_len);
|
||||
memcpy (message + message_command_len, message_nonce + nonce_prefix_len,
|
||||
sizeof (nonce_t));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int zmq::curve_encoding_t::decode (msg_t *msg_, int *error_event_code_)
|
||||
{
|
||||
int rc = check_validity (msg_, error_event_code_);
|
||||
if (0 != rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
uint8_t *const message = static_cast<uint8_t *> (msg_->data ());
|
||||
|
||||
uint8_t message_nonce[crypto_box_NONCEBYTES];
|
||||
memcpy (message_nonce, _decode_nonce_prefix, nonce_prefix_len);
|
||||
memcpy (message_nonce + nonce_prefix_len, message + message_command_len,
|
||||
sizeof (nonce_t));
|
||||
|
||||
#ifdef ZMQ_HAVE_CRYPTO_BOX_EASY_FNS
|
||||
const size_t clen = msg_->size () - message_header_len;
|
||||
|
||||
uint8_t *const message_plaintext = message + message_header_len;
|
||||
|
||||
rc = crypto_box_open_easy_afternm (message_plaintext,
|
||||
message + message_header_len, clen,
|
||||
message_nonce, _cn_precom);
|
||||
#else
|
||||
const size_t clen =
|
||||
crypto_box_BOXZEROBYTES + msg_->size () - message_header_len;
|
||||
|
||||
std::vector<uint8_t> message_plaintext_with_zerobytes (clen);
|
||||
std::vector<uint8_t> message_box (clen);
|
||||
|
||||
std::fill (message_box.begin (),
|
||||
message_box.begin () + crypto_box_BOXZEROBYTES, 0);
|
||||
memcpy (&message_box[crypto_box_BOXZEROBYTES], message + message_header_len,
|
||||
msg_->size () - message_header_len);
|
||||
|
||||
rc = crypto_box_open_afternm (&message_plaintext_with_zerobytes[0],
|
||||
&message_box[0], clen, message_nonce,
|
||||
_cn_precom);
|
||||
|
||||
const uint8_t *const message_plaintext =
|
||||
&message_plaintext_with_zerobytes[crypto_box_ZEROBYTES];
|
||||
#endif
|
||||
|
||||
if (rc == 0) {
|
||||
const uint8_t flags = message_plaintext[0];
|
||||
|
||||
#ifdef ZMQ_HAVE_CRYPTO_BOX_EASY_FNS
|
||||
const size_t plaintext_size = clen - flags_len - crypto_box_MACBYTES;
|
||||
|
||||
if (plaintext_size > 0) {
|
||||
memmove (msg_->data (), &message_plaintext[flags_len],
|
||||
plaintext_size);
|
||||
}
|
||||
|
||||
msg_->shrink (plaintext_size);
|
||||
#else
|
||||
rc = msg_->close ();
|
||||
zmq_assert (rc == 0);
|
||||
|
||||
rc = msg_->init_size (clen - flags_len - crypto_box_ZEROBYTES);
|
||||
zmq_assert (rc == 0);
|
||||
|
||||
// this is copying the data to insecure memory, so there is no point in
|
||||
// using secure_allocator_t for message_plaintext
|
||||
if (msg_->size () > 0) {
|
||||
memcpy (msg_->data (), &message_plaintext[flags_len],
|
||||
msg_->size ());
|
||||
}
|
||||
#endif
|
||||
|
||||
msg_->set_flags (flags & flag_mask);
|
||||
} else {
|
||||
// CURVE I : connection key used for MESSAGE is wrong
|
||||
*error_event_code_ = ZMQ_PROTOCOL_ERROR_ZMTP_CRYPTOGRAPHIC;
|
||||
errno = EPROTO;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
#endif
|
||||
108
3rd/libzmq/src/curve_mechanism_base.hpp
Normal file
108
3rd/libzmq/src/curve_mechanism_base.hpp
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ZMQ_CURVE_MECHANISM_BASE_HPP_INCLUDED__
|
||||
#define __ZMQ_CURVE_MECHANISM_BASE_HPP_INCLUDED__
|
||||
|
||||
#ifdef ZMQ_HAVE_CURVE
|
||||
|
||||
#if defined(ZMQ_USE_TWEETNACL)
|
||||
#include "tweetnacl.h"
|
||||
#elif defined(ZMQ_USE_LIBSODIUM)
|
||||
#include "sodium.h"
|
||||
#endif
|
||||
|
||||
#if crypto_box_NONCEBYTES != 24 || crypto_box_PUBLICKEYBYTES != 32 \
|
||||
|| crypto_box_SECRETKEYBYTES != 32 || crypto_box_ZEROBYTES != 32 \
|
||||
|| crypto_box_BOXZEROBYTES != 16 || crypto_secretbox_NONCEBYTES != 24 \
|
||||
|| crypto_secretbox_ZEROBYTES != 32 || crypto_secretbox_BOXZEROBYTES != 16
|
||||
#error "CURVE library not built properly"
|
||||
#endif
|
||||
|
||||
#include "mechanism_base.hpp"
|
||||
#include "options.hpp"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace zmq
|
||||
{
|
||||
class curve_encoding_t
|
||||
{
|
||||
public:
|
||||
curve_encoding_t (const char *encode_nonce_prefix_,
|
||||
const char *decode_nonce_prefix_,
|
||||
const bool downgrade_sub_);
|
||||
|
||||
int encode (msg_t *msg_);
|
||||
int decode (msg_t *msg_, int *error_event_code_);
|
||||
|
||||
uint8_t *get_writable_precom_buffer () { return _cn_precom; }
|
||||
const uint8_t *get_precom_buffer () const { return _cn_precom; }
|
||||
|
||||
typedef uint64_t nonce_t;
|
||||
|
||||
nonce_t get_and_inc_nonce () { return _cn_nonce++; }
|
||||
void set_peer_nonce (nonce_t peer_nonce_) { _cn_peer_nonce = peer_nonce_; };
|
||||
|
||||
private:
|
||||
int check_validity (msg_t *msg_, int *error_event_code_);
|
||||
|
||||
const char *_encode_nonce_prefix;
|
||||
const char *_decode_nonce_prefix;
|
||||
|
||||
nonce_t _cn_nonce;
|
||||
nonce_t _cn_peer_nonce;
|
||||
|
||||
// Intermediary buffer used to speed up boxing and unboxing.
|
||||
uint8_t _cn_precom[crypto_box_BEFORENMBYTES];
|
||||
|
||||
const bool _downgrade_sub;
|
||||
|
||||
ZMQ_NON_COPYABLE_NOR_MOVABLE (curve_encoding_t)
|
||||
};
|
||||
|
||||
class curve_mechanism_base_t : public virtual mechanism_base_t,
|
||||
public curve_encoding_t
|
||||
{
|
||||
public:
|
||||
curve_mechanism_base_t (session_base_t *session_,
|
||||
const options_t &options_,
|
||||
const char *encode_nonce_prefix_,
|
||||
const char *decode_nonce_prefix_,
|
||||
const bool downgrade_sub_);
|
||||
|
||||
// mechanism implementation
|
||||
int encode (msg_t *msg_) ZMQ_OVERRIDE;
|
||||
int decode (msg_t *msg_) ZMQ_OVERRIDE;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
506
3rd/libzmq/src/curve_server.cpp
Normal file
506
3rd/libzmq/src/curve_server.cpp
Normal file
@@ -0,0 +1,506 @@
|
||||
/*
|
||||
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "macros.hpp"
|
||||
|
||||
#ifdef ZMQ_HAVE_CURVE
|
||||
|
||||
#include "msg.hpp"
|
||||
#include "session_base.hpp"
|
||||
#include "err.hpp"
|
||||
#include "curve_server.hpp"
|
||||
#include "wire.hpp"
|
||||
#include "secure_allocator.hpp"
|
||||
|
||||
zmq::curve_server_t::curve_server_t (session_base_t *session_,
|
||||
const std::string &peer_address_,
|
||||
const options_t &options_,
|
||||
const bool downgrade_sub_) :
|
||||
mechanism_base_t (session_, options_),
|
||||
zap_client_common_handshake_t (
|
||||
session_, peer_address_, options_, sending_ready),
|
||||
curve_mechanism_base_t (session_,
|
||||
options_,
|
||||
"CurveZMQMESSAGES",
|
||||
"CurveZMQMESSAGEC",
|
||||
downgrade_sub_)
|
||||
{
|
||||
int rc;
|
||||
// Fetch our secret key from socket options
|
||||
memcpy (_secret_key, options_.curve_secret_key, crypto_box_SECRETKEYBYTES);
|
||||
|
||||
// Generate short-term key pair
|
||||
memset (_cn_secret, 0, crypto_box_SECRETKEYBYTES);
|
||||
memset (_cn_public, 0, crypto_box_PUBLICKEYBYTES);
|
||||
rc = crypto_box_keypair (_cn_public, _cn_secret);
|
||||
zmq_assert (rc == 0);
|
||||
}
|
||||
|
||||
zmq::curve_server_t::~curve_server_t ()
|
||||
{
|
||||
}
|
||||
|
||||
int zmq::curve_server_t::next_handshake_command (msg_t *msg_)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
switch (state) {
|
||||
case sending_welcome:
|
||||
rc = produce_welcome (msg_);
|
||||
if (rc == 0)
|
||||
state = waiting_for_initiate;
|
||||
break;
|
||||
case sending_ready:
|
||||
rc = produce_ready (msg_);
|
||||
if (rc == 0)
|
||||
state = ready;
|
||||
break;
|
||||
case sending_error:
|
||||
rc = produce_error (msg_);
|
||||
if (rc == 0)
|
||||
state = error_sent;
|
||||
break;
|
||||
default:
|
||||
errno = EAGAIN;
|
||||
rc = -1;
|
||||
break;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int zmq::curve_server_t::process_handshake_command (msg_t *msg_)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
switch (state) {
|
||||
case waiting_for_hello:
|
||||
rc = process_hello (msg_);
|
||||
break;
|
||||
case waiting_for_initiate:
|
||||
rc = process_initiate (msg_);
|
||||
break;
|
||||
default:
|
||||
// TODO I think this is not a case reachable with a misbehaving
|
||||
// client. It is not an "invalid handshake command", but would be
|
||||
// trying to process a handshake command in an invalid state,
|
||||
// which is purely under control of this peer.
|
||||
// Therefore, it should be changed to zmq_assert (false);
|
||||
|
||||
// CURVE I: invalid handshake command
|
||||
session->get_socket ()->event_handshake_failed_protocol (
|
||||
session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZMTP_UNSPECIFIED);
|
||||
errno = EPROTO;
|
||||
rc = -1;
|
||||
break;
|
||||
}
|
||||
if (rc == 0) {
|
||||
rc = msg_->close ();
|
||||
errno_assert (rc == 0);
|
||||
rc = msg_->init ();
|
||||
errno_assert (rc == 0);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int zmq::curve_server_t::encode (msg_t *msg_)
|
||||
{
|
||||
zmq_assert (state == ready);
|
||||
return curve_mechanism_base_t::encode (msg_);
|
||||
}
|
||||
|
||||
int zmq::curve_server_t::decode (msg_t *msg_)
|
||||
{
|
||||
zmq_assert (state == ready);
|
||||
return curve_mechanism_base_t::decode (msg_);
|
||||
}
|
||||
|
||||
int zmq::curve_server_t::process_hello (msg_t *msg_)
|
||||
{
|
||||
int rc = check_basic_command_structure (msg_);
|
||||
if (rc == -1)
|
||||
return -1;
|
||||
|
||||
const size_t size = msg_->size ();
|
||||
const uint8_t *const hello = static_cast<uint8_t *> (msg_->data ());
|
||||
|
||||
if (size < 6 || memcmp (hello, "\x05HELLO", 6)) {
|
||||
session->get_socket ()->event_handshake_failed_protocol (
|
||||
session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZMTP_UNEXPECTED_COMMAND);
|
||||
errno = EPROTO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (size != 200) {
|
||||
session->get_socket ()->event_handshake_failed_protocol (
|
||||
session->get_endpoint (),
|
||||
ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_HELLO);
|
||||
errno = EPROTO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
const uint8_t major = hello[6];
|
||||
const uint8_t minor = hello[7];
|
||||
|
||||
if (major != 1 || minor != 0) {
|
||||
// CURVE I: client HELLO has unknown version number
|
||||
session->get_socket ()->event_handshake_failed_protocol (
|
||||
session->get_endpoint (),
|
||||
ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_HELLO);
|
||||
errno = EPROTO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Save client's short-term public key (C')
|
||||
memcpy (_cn_client, hello + 80, 32);
|
||||
|
||||
uint8_t hello_nonce[crypto_box_NONCEBYTES];
|
||||
std::vector<uint8_t, secure_allocator_t<uint8_t> > hello_plaintext (
|
||||
crypto_box_ZEROBYTES + 64);
|
||||
uint8_t hello_box[crypto_box_BOXZEROBYTES + 80];
|
||||
|
||||
memcpy (hello_nonce, "CurveZMQHELLO---", 16);
|
||||
memcpy (hello_nonce + 16, hello + 112, 8);
|
||||
set_peer_nonce (get_uint64 (hello + 112));
|
||||
|
||||
memset (hello_box, 0, crypto_box_BOXZEROBYTES);
|
||||
memcpy (hello_box + crypto_box_BOXZEROBYTES, hello + 120, 80);
|
||||
|
||||
// Open Box [64 * %x0](C'->S)
|
||||
rc = crypto_box_open (&hello_plaintext[0], hello_box, sizeof hello_box,
|
||||
hello_nonce, _cn_client, _secret_key);
|
||||
if (rc != 0) {
|
||||
// CURVE I: cannot open client HELLO -- wrong server key?
|
||||
session->get_socket ()->event_handshake_failed_protocol (
|
||||
session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZMTP_CRYPTOGRAPHIC);
|
||||
errno = EPROTO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
state = sending_welcome;
|
||||
return rc;
|
||||
}
|
||||
|
||||
int zmq::curve_server_t::produce_welcome (msg_t *msg_)
|
||||
{
|
||||
uint8_t cookie_nonce[crypto_secretbox_NONCEBYTES];
|
||||
std::vector<uint8_t, secure_allocator_t<uint8_t> > cookie_plaintext (
|
||||
crypto_secretbox_ZEROBYTES + 64);
|
||||
uint8_t cookie_ciphertext[crypto_secretbox_BOXZEROBYTES + 80];
|
||||
|
||||
// Create full nonce for encryption
|
||||
// 8-byte prefix plus 16-byte random nonce
|
||||
memset (cookie_nonce, 0, crypto_secretbox_NONCEBYTES);
|
||||
memcpy (cookie_nonce, "COOKIE--", 8);
|
||||
randombytes (cookie_nonce + 8, 16);
|
||||
|
||||
// Generate cookie = Box [C' + s'](t)
|
||||
std::fill (cookie_plaintext.begin (),
|
||||
cookie_plaintext.begin () + crypto_secretbox_ZEROBYTES, 0);
|
||||
memcpy (&cookie_plaintext[crypto_secretbox_ZEROBYTES], _cn_client, 32);
|
||||
memcpy (&cookie_plaintext[crypto_secretbox_ZEROBYTES + 32], _cn_secret, 32);
|
||||
|
||||
// Generate fresh cookie key
|
||||
memset (_cookie_key, 0, crypto_secretbox_KEYBYTES);
|
||||
randombytes (_cookie_key, crypto_secretbox_KEYBYTES);
|
||||
|
||||
// Encrypt using symmetric cookie key
|
||||
int rc =
|
||||
crypto_secretbox (cookie_ciphertext, &cookie_plaintext[0],
|
||||
cookie_plaintext.size (), cookie_nonce, _cookie_key);
|
||||
zmq_assert (rc == 0);
|
||||
|
||||
uint8_t welcome_nonce[crypto_box_NONCEBYTES];
|
||||
std::vector<uint8_t, secure_allocator_t<uint8_t> > welcome_plaintext (
|
||||
crypto_box_ZEROBYTES + 128);
|
||||
uint8_t welcome_ciphertext[crypto_box_BOXZEROBYTES + 144];
|
||||
|
||||
// Create full nonce for encryption
|
||||
// 8-byte prefix plus 16-byte random nonce
|
||||
memset (welcome_nonce, 0, crypto_box_NONCEBYTES);
|
||||
memcpy (welcome_nonce, "WELCOME-", 8);
|
||||
randombytes (welcome_nonce + 8, crypto_box_NONCEBYTES - 8);
|
||||
|
||||
// Create 144-byte Box [S' + cookie](S->C')
|
||||
std::fill (welcome_plaintext.begin (),
|
||||
welcome_plaintext.begin () + crypto_box_ZEROBYTES, 0);
|
||||
memcpy (&welcome_plaintext[crypto_box_ZEROBYTES], _cn_public, 32);
|
||||
memcpy (&welcome_plaintext[crypto_box_ZEROBYTES + 32], cookie_nonce + 8,
|
||||
16);
|
||||
memcpy (&welcome_plaintext[crypto_box_ZEROBYTES + 48],
|
||||
cookie_ciphertext + crypto_secretbox_BOXZEROBYTES, 80);
|
||||
|
||||
rc = crypto_box (welcome_ciphertext, &welcome_plaintext[0],
|
||||
welcome_plaintext.size (), welcome_nonce, _cn_client,
|
||||
_secret_key);
|
||||
|
||||
// TODO I think we should change this back to zmq_assert (rc == 0);
|
||||
// as it was before https://github.com/zeromq/libzmq/pull/1832
|
||||
// The reason given there was that secret_key might be 0ed.
|
||||
// But if it were, we would never get this far, since we could
|
||||
// not have opened the client's hello box with a 0ed key.
|
||||
|
||||
if (rc == -1)
|
||||
return -1;
|
||||
|
||||
rc = msg_->init_size (168);
|
||||
errno_assert (rc == 0);
|
||||
|
||||
uint8_t *const welcome = static_cast<uint8_t *> (msg_->data ());
|
||||
memcpy (welcome, "\x07WELCOME", 8);
|
||||
memcpy (welcome + 8, welcome_nonce + 8, 16);
|
||||
memcpy (welcome + 24, welcome_ciphertext + crypto_box_BOXZEROBYTES, 144);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int zmq::curve_server_t::process_initiate (msg_t *msg_)
|
||||
{
|
||||
int rc = check_basic_command_structure (msg_);
|
||||
if (rc == -1)
|
||||
return -1;
|
||||
|
||||
const size_t size = msg_->size ();
|
||||
const uint8_t *initiate = static_cast<uint8_t *> (msg_->data ());
|
||||
|
||||
if (size < 9 || memcmp (initiate, "\x08INITIATE", 9)) {
|
||||
session->get_socket ()->event_handshake_failed_protocol (
|
||||
session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZMTP_UNEXPECTED_COMMAND);
|
||||
errno = EPROTO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (size < 257) {
|
||||
session->get_socket ()->event_handshake_failed_protocol (
|
||||
session->get_endpoint (),
|
||||
ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_INITIATE);
|
||||
errno = EPROTO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t cookie_nonce[crypto_secretbox_NONCEBYTES];
|
||||
uint8_t cookie_plaintext[crypto_secretbox_ZEROBYTES + 64];
|
||||
uint8_t cookie_box[crypto_secretbox_BOXZEROBYTES + 80];
|
||||
|
||||
// Open Box [C' + s'](t)
|
||||
memset (cookie_box, 0, crypto_secretbox_BOXZEROBYTES);
|
||||
memcpy (cookie_box + crypto_secretbox_BOXZEROBYTES, initiate + 25, 80);
|
||||
|
||||
memcpy (cookie_nonce, "COOKIE--", 8);
|
||||
memcpy (cookie_nonce + 8, initiate + 9, 16);
|
||||
|
||||
rc = crypto_secretbox_open (cookie_plaintext, cookie_box, sizeof cookie_box,
|
||||
cookie_nonce, _cookie_key);
|
||||
if (rc != 0) {
|
||||
// CURVE I: cannot open client INITIATE cookie
|
||||
session->get_socket ()->event_handshake_failed_protocol (
|
||||
session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZMTP_CRYPTOGRAPHIC);
|
||||
errno = EPROTO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Check cookie plain text is as expected [C' + s']
|
||||
if (memcmp (cookie_plaintext + crypto_secretbox_ZEROBYTES, _cn_client, 32)
|
||||
|| memcmp (cookie_plaintext + crypto_secretbox_ZEROBYTES + 32,
|
||||
_cn_secret, 32)) {
|
||||
// TODO this case is very hard to test, as it would require a modified
|
||||
// client that knows the server's secret temporary cookie key
|
||||
|
||||
// CURVE I: client INITIATE cookie is not valid
|
||||
session->get_socket ()->event_handshake_failed_protocol (
|
||||
session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZMTP_CRYPTOGRAPHIC);
|
||||
errno = EPROTO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
const size_t clen = (size - 113) + crypto_box_BOXZEROBYTES;
|
||||
|
||||
uint8_t initiate_nonce[crypto_box_NONCEBYTES];
|
||||
std::vector<uint8_t, secure_allocator_t<uint8_t> > initiate_plaintext (
|
||||
crypto_box_ZEROBYTES + clen);
|
||||
std::vector<uint8_t> initiate_box (crypto_box_BOXZEROBYTES + clen);
|
||||
|
||||
// Open Box [C + vouch + metadata](C'->S')
|
||||
std::fill (initiate_box.begin (),
|
||||
initiate_box.begin () + crypto_box_BOXZEROBYTES, 0);
|
||||
memcpy (&initiate_box[crypto_box_BOXZEROBYTES], initiate + 113,
|
||||
clen - crypto_box_BOXZEROBYTES);
|
||||
|
||||
memcpy (initiate_nonce, "CurveZMQINITIATE", 16);
|
||||
memcpy (initiate_nonce + 16, initiate + 105, 8);
|
||||
set_peer_nonce (get_uint64 (initiate + 105));
|
||||
|
||||
const uint8_t *client_key = &initiate_plaintext[crypto_box_ZEROBYTES];
|
||||
|
||||
rc = crypto_box_open (&initiate_plaintext[0], &initiate_box[0], clen,
|
||||
initiate_nonce, _cn_client, _cn_secret);
|
||||
if (rc != 0) {
|
||||
// CURVE I: cannot open client INITIATE
|
||||
session->get_socket ()->event_handshake_failed_protocol (
|
||||
session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZMTP_CRYPTOGRAPHIC);
|
||||
errno = EPROTO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t vouch_nonce[crypto_box_NONCEBYTES];
|
||||
std::vector<uint8_t, secure_allocator_t<uint8_t> > vouch_plaintext (
|
||||
crypto_box_ZEROBYTES + 64);
|
||||
uint8_t vouch_box[crypto_box_BOXZEROBYTES + 80];
|
||||
|
||||
// Open Box Box [C',S](C->S') and check contents
|
||||
memset (vouch_box, 0, crypto_box_BOXZEROBYTES);
|
||||
memcpy (vouch_box + crypto_box_BOXZEROBYTES,
|
||||
&initiate_plaintext[crypto_box_ZEROBYTES + 48], 80);
|
||||
|
||||
memset (vouch_nonce, 0, crypto_box_NONCEBYTES);
|
||||
memcpy (vouch_nonce, "VOUCH---", 8);
|
||||
memcpy (vouch_nonce + 8, &initiate_plaintext[crypto_box_ZEROBYTES + 32],
|
||||
16);
|
||||
|
||||
rc = crypto_box_open (&vouch_plaintext[0], vouch_box, sizeof vouch_box,
|
||||
vouch_nonce, client_key, _cn_secret);
|
||||
if (rc != 0) {
|
||||
// CURVE I: cannot open client INITIATE vouch
|
||||
session->get_socket ()->event_handshake_failed_protocol (
|
||||
session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZMTP_CRYPTOGRAPHIC);
|
||||
errno = EPROTO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// What we decrypted must be the client's short-term public key
|
||||
if (memcmp (&vouch_plaintext[crypto_box_ZEROBYTES], _cn_client, 32)) {
|
||||
// TODO this case is very hard to test, as it would require a modified
|
||||
// client that knows the server's secret short-term key
|
||||
|
||||
// CURVE I: invalid handshake from client (public key)
|
||||
session->get_socket ()->event_handshake_failed_protocol (
|
||||
session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZMTP_KEY_EXCHANGE);
|
||||
errno = EPROTO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Precompute connection secret from client key
|
||||
rc = crypto_box_beforenm (get_writable_precom_buffer (), _cn_client,
|
||||
_cn_secret);
|
||||
zmq_assert (rc == 0);
|
||||
|
||||
// Given this is a backward-incompatible change, it's behind a socket
|
||||
// option disabled by default.
|
||||
if (zap_required () || !options.zap_enforce_domain) {
|
||||
// Use ZAP protocol (RFC 27) to authenticate the user.
|
||||
rc = session->zap_connect ();
|
||||
if (rc == 0) {
|
||||
send_zap_request (client_key);
|
||||
state = waiting_for_zap_reply;
|
||||
|
||||
// TODO actually, it is quite unlikely that we can read the ZAP
|
||||
// reply already, but removing this has some strange side-effect
|
||||
// (probably because the pipe's in_active flag is true until a read
|
||||
// is attempted)
|
||||
if (-1 == receive_and_process_zap_reply ())
|
||||
return -1;
|
||||
} else if (!options.zap_enforce_domain) {
|
||||
// This supports the Stonehouse pattern (encryption without
|
||||
// authentication) in legacy mode (domain set but no handler).
|
||||
state = sending_ready;
|
||||
} else {
|
||||
session->get_socket ()->event_handshake_failed_no_detail (
|
||||
session->get_endpoint (), EFAULT);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
// This supports the Stonehouse pattern (encryption without authentication).
|
||||
state = sending_ready;
|
||||
}
|
||||
|
||||
return parse_metadata (&initiate_plaintext[crypto_box_ZEROBYTES + 128],
|
||||
clen - crypto_box_ZEROBYTES - 128);
|
||||
}
|
||||
|
||||
int zmq::curve_server_t::produce_ready (msg_t *msg_)
|
||||
{
|
||||
const size_t metadata_length = basic_properties_len ();
|
||||
uint8_t ready_nonce[crypto_box_NONCEBYTES];
|
||||
|
||||
std::vector<uint8_t, secure_allocator_t<uint8_t> > ready_plaintext (
|
||||
crypto_box_ZEROBYTES + metadata_length);
|
||||
|
||||
// Create Box [metadata](S'->C')
|
||||
std::fill (ready_plaintext.begin (),
|
||||
ready_plaintext.begin () + crypto_box_ZEROBYTES, 0);
|
||||
uint8_t *ptr = &ready_plaintext[crypto_box_ZEROBYTES];
|
||||
|
||||
ptr += add_basic_properties (ptr, metadata_length);
|
||||
const size_t mlen = ptr - &ready_plaintext[0];
|
||||
|
||||
memcpy (ready_nonce, "CurveZMQREADY---", 16);
|
||||
put_uint64 (ready_nonce + 16, get_and_inc_nonce ());
|
||||
|
||||
std::vector<uint8_t> ready_box (crypto_box_BOXZEROBYTES + 16
|
||||
+ metadata_length);
|
||||
|
||||
int rc = crypto_box_afternm (&ready_box[0], &ready_plaintext[0], mlen,
|
||||
ready_nonce, get_precom_buffer ());
|
||||
zmq_assert (rc == 0);
|
||||
|
||||
rc = msg_->init_size (14 + mlen - crypto_box_BOXZEROBYTES);
|
||||
errno_assert (rc == 0);
|
||||
|
||||
uint8_t *ready = static_cast<uint8_t *> (msg_->data ());
|
||||
|
||||
memcpy (ready, "\x05READY", 6);
|
||||
// Short nonce, prefixed by "CurveZMQREADY---"
|
||||
memcpy (ready + 6, ready_nonce + 16, 8);
|
||||
// Box [metadata](S'->C')
|
||||
memcpy (ready + 14, &ready_box[crypto_box_BOXZEROBYTES],
|
||||
mlen - crypto_box_BOXZEROBYTES);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int zmq::curve_server_t::produce_error (msg_t *msg_) const
|
||||
{
|
||||
const size_t expected_status_code_length = 3;
|
||||
zmq_assert (status_code.length () == 3);
|
||||
const int rc = msg_->init_size (6 + 1 + expected_status_code_length);
|
||||
zmq_assert (rc == 0);
|
||||
char *msg_data = static_cast<char *> (msg_->data ());
|
||||
memcpy (msg_data, "\5ERROR", 6);
|
||||
msg_data[6] = expected_status_code_length;
|
||||
memcpy (msg_data + 7, status_code.c_str (), expected_status_code_length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void zmq::curve_server_t::send_zap_request (const uint8_t *key_)
|
||||
{
|
||||
zap_client_t::send_zap_request ("CURVE", 5, key_,
|
||||
crypto_box_PUBLICKEYBYTES);
|
||||
}
|
||||
|
||||
#endif
|
||||
92
3rd/libzmq/src/curve_server.hpp
Normal file
92
3rd/libzmq/src/curve_server.hpp
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ZMQ_CURVE_SERVER_HPP_INCLUDED__
|
||||
#define __ZMQ_CURVE_SERVER_HPP_INCLUDED__
|
||||
|
||||
#ifdef ZMQ_HAVE_CURVE
|
||||
|
||||
#include "curve_mechanism_base.hpp"
|
||||
#include "options.hpp"
|
||||
#include "zap_client.hpp"
|
||||
|
||||
namespace zmq
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4250)
|
||||
#endif
|
||||
class curve_server_t ZMQ_FINAL : public zap_client_common_handshake_t,
|
||||
public curve_mechanism_base_t
|
||||
{
|
||||
public:
|
||||
curve_server_t (session_base_t *session_,
|
||||
const std::string &peer_address_,
|
||||
const options_t &options_,
|
||||
const bool downgrade_sub_);
|
||||
~curve_server_t ();
|
||||
|
||||
// mechanism implementation
|
||||
int next_handshake_command (msg_t *msg_);
|
||||
int process_handshake_command (msg_t *msg_);
|
||||
int encode (msg_t *msg_);
|
||||
int decode (msg_t *msg_);
|
||||
|
||||
private:
|
||||
// Our secret key (s)
|
||||
uint8_t _secret_key[crypto_box_SECRETKEYBYTES];
|
||||
|
||||
// Our short-term public key (S')
|
||||
uint8_t _cn_public[crypto_box_PUBLICKEYBYTES];
|
||||
|
||||
// Our short-term secret key (s')
|
||||
uint8_t _cn_secret[crypto_box_SECRETKEYBYTES];
|
||||
|
||||
// Client's short-term public key (C')
|
||||
uint8_t _cn_client[crypto_box_PUBLICKEYBYTES];
|
||||
|
||||
// Key used to produce cookie
|
||||
uint8_t _cookie_key[crypto_secretbox_KEYBYTES];
|
||||
|
||||
int process_hello (msg_t *msg_);
|
||||
int produce_welcome (msg_t *msg_);
|
||||
int process_initiate (msg_t *msg_);
|
||||
int produce_ready (msg_t *msg_);
|
||||
int produce_error (msg_t *msg_) const;
|
||||
|
||||
void send_zap_request (const uint8_t *key_);
|
||||
};
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
134
3rd/libzmq/src/dbuffer.hpp
Normal file
134
3rd/libzmq/src/dbuffer.hpp
Normal file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ZMQ_DBUFFER_HPP_INCLUDED__
|
||||
#define __ZMQ_DBUFFER_HPP_INCLUDED__
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <algorithm>
|
||||
|
||||
#include "mutex.hpp"
|
||||
#include "msg.hpp"
|
||||
|
||||
namespace zmq
|
||||
{
|
||||
// dbuffer is a single-producer single-consumer double-buffer
|
||||
// implementation.
|
||||
//
|
||||
// The producer writes to a back buffer and then tries to swap
|
||||
// pointers between the back and front buffers. If it fails,
|
||||
// due to the consumer reading from the front buffer, it just
|
||||
// gives up, which is ok since writes are many and redundant.
|
||||
//
|
||||
// The reader simply reads from the front buffer.
|
||||
//
|
||||
// has_msg keeps track of whether there has been a not yet read
|
||||
// value written, it is used by ypipe_conflate to mimic ypipe
|
||||
// functionality regarding a reader being asleep
|
||||
|
||||
template <typename T> class dbuffer_t;
|
||||
|
||||
template <> class dbuffer_t<msg_t>
|
||||
{
|
||||
public:
|
||||
dbuffer_t () : _back (&_storage[0]), _front (&_storage[1]), _has_msg (false)
|
||||
{
|
||||
_back->init ();
|
||||
_front->init ();
|
||||
}
|
||||
|
||||
~dbuffer_t ()
|
||||
{
|
||||
_back->close ();
|
||||
_front->close ();
|
||||
}
|
||||
|
||||
void write (const msg_t &value_)
|
||||
{
|
||||
zmq_assert (value_.check ());
|
||||
*_back = value_;
|
||||
|
||||
zmq_assert (_back->check ());
|
||||
|
||||
if (_sync.try_lock ()) {
|
||||
_front->move (*_back);
|
||||
_has_msg = true;
|
||||
|
||||
_sync.unlock ();
|
||||
}
|
||||
}
|
||||
|
||||
bool read (msg_t *value_)
|
||||
{
|
||||
if (!value_)
|
||||
return false;
|
||||
|
||||
{
|
||||
scoped_lock_t lock (_sync);
|
||||
if (!_has_msg)
|
||||
return false;
|
||||
|
||||
zmq_assert (_front->check ());
|
||||
|
||||
*value_ = *_front;
|
||||
_front->init (); // avoid double free
|
||||
|
||||
_has_msg = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool check_read ()
|
||||
{
|
||||
scoped_lock_t lock (_sync);
|
||||
|
||||
return _has_msg;
|
||||
}
|
||||
|
||||
bool probe (bool (*fn_) (const msg_t &))
|
||||
{
|
||||
scoped_lock_t lock (_sync);
|
||||
return (*fn_) (*_front);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
msg_t _storage[2];
|
||||
msg_t *_back, *_front;
|
||||
|
||||
mutex_t _sync;
|
||||
bool _has_msg;
|
||||
|
||||
ZMQ_NON_COPYABLE_NOR_MOVABLE (dbuffer_t)
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
145
3rd/libzmq/src/dealer.cpp
Normal file
145
3rd/libzmq/src/dealer.cpp
Normal file
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "macros.hpp"
|
||||
#include "dealer.hpp"
|
||||
#include "err.hpp"
|
||||
#include "msg.hpp"
|
||||
|
||||
zmq::dealer_t::dealer_t (class ctx_t *parent_, uint32_t tid_, int sid_) :
|
||||
socket_base_t (parent_, tid_, sid_),
|
||||
_probe_router (false)
|
||||
{
|
||||
options.type = ZMQ_DEALER;
|
||||
options.can_send_hello_msg = true;
|
||||
}
|
||||
|
||||
zmq::dealer_t::~dealer_t ()
|
||||
{
|
||||
}
|
||||
|
||||
void zmq::dealer_t::xattach_pipe (pipe_t *pipe_,
|
||||
bool subscribe_to_all_,
|
||||
bool locally_initiated_)
|
||||
{
|
||||
LIBZMQ_UNUSED (subscribe_to_all_);
|
||||
LIBZMQ_UNUSED (locally_initiated_);
|
||||
|
||||
zmq_assert (pipe_);
|
||||
|
||||
if (_probe_router) {
|
||||
msg_t probe_msg;
|
||||
int rc = probe_msg.init ();
|
||||
errno_assert (rc == 0);
|
||||
|
||||
rc = pipe_->write (&probe_msg);
|
||||
// zmq_assert (rc) is not applicable here, since it is not a bug.
|
||||
LIBZMQ_UNUSED (rc);
|
||||
|
||||
pipe_->flush ();
|
||||
|
||||
rc = probe_msg.close ();
|
||||
errno_assert (rc == 0);
|
||||
}
|
||||
|
||||
_fq.attach (pipe_);
|
||||
_lb.attach (pipe_);
|
||||
}
|
||||
|
||||
int zmq::dealer_t::xsetsockopt (int option_,
|
||||
const void *optval_,
|
||||
size_t optvallen_)
|
||||
{
|
||||
const bool is_int = (optvallen_ == sizeof (int));
|
||||
int value = 0;
|
||||
if (is_int)
|
||||
memcpy (&value, optval_, sizeof (int));
|
||||
|
||||
switch (option_) {
|
||||
case ZMQ_PROBE_ROUTER:
|
||||
if (is_int && value >= 0) {
|
||||
_probe_router = (value != 0);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int zmq::dealer_t::xsend (msg_t *msg_)
|
||||
{
|
||||
return sendpipe (msg_, NULL);
|
||||
}
|
||||
|
||||
int zmq::dealer_t::xrecv (msg_t *msg_)
|
||||
{
|
||||
return recvpipe (msg_, NULL);
|
||||
}
|
||||
|
||||
bool zmq::dealer_t::xhas_in ()
|
||||
{
|
||||
return _fq.has_in ();
|
||||
}
|
||||
|
||||
bool zmq::dealer_t::xhas_out ()
|
||||
{
|
||||
return _lb.has_out ();
|
||||
}
|
||||
|
||||
void zmq::dealer_t::xread_activated (pipe_t *pipe_)
|
||||
{
|
||||
_fq.activated (pipe_);
|
||||
}
|
||||
|
||||
void zmq::dealer_t::xwrite_activated (pipe_t *pipe_)
|
||||
{
|
||||
_lb.activated (pipe_);
|
||||
}
|
||||
|
||||
void zmq::dealer_t::xpipe_terminated (pipe_t *pipe_)
|
||||
{
|
||||
_fq.pipe_terminated (pipe_);
|
||||
_lb.pipe_terminated (pipe_);
|
||||
}
|
||||
|
||||
int zmq::dealer_t::sendpipe (msg_t *msg_, pipe_t **pipe_)
|
||||
{
|
||||
return _lb.sendpipe (msg_, pipe_);
|
||||
}
|
||||
|
||||
int zmq::dealer_t::recvpipe (msg_t *msg_, pipe_t **pipe_)
|
||||
{
|
||||
return _fq.recvpipe (msg_, pipe_);
|
||||
}
|
||||
85
3rd/libzmq/src/dealer.hpp
Normal file
85
3rd/libzmq/src/dealer.hpp
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ZMQ_DEALER_HPP_INCLUDED__
|
||||
#define __ZMQ_DEALER_HPP_INCLUDED__
|
||||
|
||||
#include "socket_base.hpp"
|
||||
#include "session_base.hpp"
|
||||
#include "fq.hpp"
|
||||
#include "lb.hpp"
|
||||
|
||||
namespace zmq
|
||||
{
|
||||
class ctx_t;
|
||||
class msg_t;
|
||||
class pipe_t;
|
||||
class io_thread_t;
|
||||
class socket_base_t;
|
||||
|
||||
class dealer_t : public socket_base_t
|
||||
{
|
||||
public:
|
||||
dealer_t (zmq::ctx_t *parent_, uint32_t tid_, int sid_);
|
||||
~dealer_t () ZMQ_OVERRIDE;
|
||||
|
||||
protected:
|
||||
// Overrides of functions from socket_base_t.
|
||||
void xattach_pipe (zmq::pipe_t *pipe_,
|
||||
bool subscribe_to_all_,
|
||||
bool locally_initiated_) ZMQ_FINAL;
|
||||
int xsetsockopt (int option_,
|
||||
const void *optval_,
|
||||
size_t optvallen_) ZMQ_OVERRIDE;
|
||||
int xsend (zmq::msg_t *msg_) ZMQ_OVERRIDE;
|
||||
int xrecv (zmq::msg_t *msg_) ZMQ_OVERRIDE;
|
||||
bool xhas_in () ZMQ_OVERRIDE;
|
||||
bool xhas_out () ZMQ_OVERRIDE;
|
||||
void xread_activated (zmq::pipe_t *pipe_) ZMQ_FINAL;
|
||||
void xwrite_activated (zmq::pipe_t *pipe_) ZMQ_FINAL;
|
||||
void xpipe_terminated (zmq::pipe_t *pipe_) ZMQ_OVERRIDE;
|
||||
|
||||
// Send and recv - knowing which pipe was used.
|
||||
int sendpipe (zmq::msg_t *msg_, zmq::pipe_t **pipe_);
|
||||
int recvpipe (zmq::msg_t *msg_, zmq::pipe_t **pipe_);
|
||||
|
||||
private:
|
||||
// Messages are fair-queued from inbound pipes. And load-balanced to
|
||||
// the outbound pipes.
|
||||
fq_t _fq;
|
||||
lb_t _lb;
|
||||
|
||||
// if true, send an empty message to every connected router peer
|
||||
bool _probe_router;
|
||||
|
||||
ZMQ_NON_COPYABLE_NOR_MOVABLE (dealer_t)
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
191
3rd/libzmq/src/decoder.hpp
Normal file
191
3rd/libzmq/src/decoder.hpp
Normal file
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ZMQ_DECODER_HPP_INCLUDED__
|
||||
#define __ZMQ_DECODER_HPP_INCLUDED__
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
|
||||
#include "decoder_allocators.hpp"
|
||||
#include "err.hpp"
|
||||
#include "i_decoder.hpp"
|
||||
#include "stdint.hpp"
|
||||
|
||||
namespace zmq
|
||||
{
|
||||
// Helper base class for decoders that know the amount of data to read
|
||||
// in advance at any moment. Knowing the amount in advance is a property
|
||||
// of the protocol used. 0MQ framing protocol is based size-prefixed
|
||||
// paradigm, which qualifies it to be parsed by this class.
|
||||
// On the other hand, XML-based transports (like XMPP or SOAP) don't allow
|
||||
// for knowing the size of data to read in advance and should use different
|
||||
// decoding algorithms.
|
||||
//
|
||||
// This class implements the state machine that parses the incoming buffer.
|
||||
// Derived class should implement individual state machine actions.
|
||||
//
|
||||
// Buffer management is done by an allocator policy.
|
||||
template <typename T, typename A = c_single_allocator>
|
||||
class decoder_base_t : public i_decoder
|
||||
{
|
||||
public:
|
||||
explicit decoder_base_t (const size_t buf_size_) :
|
||||
_next (NULL),
|
||||
_read_pos (NULL),
|
||||
_to_read (0),
|
||||
_allocator (buf_size_)
|
||||
{
|
||||
_buf = _allocator.allocate ();
|
||||
}
|
||||
|
||||
~decoder_base_t () ZMQ_OVERRIDE { _allocator.deallocate (); }
|
||||
|
||||
// Returns a buffer to be filled with binary data.
|
||||
void get_buffer (unsigned char **data_, std::size_t *size_) ZMQ_FINAL
|
||||
{
|
||||
_buf = _allocator.allocate ();
|
||||
|
||||
// If we are expected to read large message, we'll opt for zero-
|
||||
// copy, i.e. we'll ask caller to fill the data directly to the
|
||||
// message. Note that subsequent read(s) are non-blocking, thus
|
||||
// each single read reads at most SO_RCVBUF bytes at once not
|
||||
// depending on how large is the chunk returned from here.
|
||||
// As a consequence, large messages being received won't block
|
||||
// other engines running in the same I/O thread for excessive
|
||||
// amounts of time.
|
||||
if (_to_read >= _allocator.size ()) {
|
||||
*data_ = _read_pos;
|
||||
*size_ = _to_read;
|
||||
return;
|
||||
}
|
||||
|
||||
*data_ = _buf;
|
||||
*size_ = _allocator.size ();
|
||||
}
|
||||
|
||||
// Processes the data in the buffer previously allocated using
|
||||
// get_buffer function. size_ argument specifies number of bytes
|
||||
// actually filled into the buffer. Function returns 1 when the
|
||||
// whole message was decoded or 0 when more data is required.
|
||||
// On error, -1 is returned and errno set accordingly.
|
||||
// Number of bytes processed is returned in bytes_used_.
|
||||
int decode (const unsigned char *data_,
|
||||
std::size_t size_,
|
||||
std::size_t &bytes_used_) ZMQ_FINAL
|
||||
{
|
||||
bytes_used_ = 0;
|
||||
|
||||
// In case of zero-copy simply adjust the pointers, no copying
|
||||
// is required. Also, run the state machine in case all the data
|
||||
// were processed.
|
||||
if (data_ == _read_pos) {
|
||||
zmq_assert (size_ <= _to_read);
|
||||
_read_pos += size_;
|
||||
_to_read -= size_;
|
||||
bytes_used_ = size_;
|
||||
|
||||
while (!_to_read) {
|
||||
const int rc =
|
||||
(static_cast<T *> (this)->*_next) (data_ + bytes_used_);
|
||||
if (rc != 0)
|
||||
return rc;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (bytes_used_ < size_) {
|
||||
// Copy the data from buffer to the message.
|
||||
const size_t to_copy = std::min (_to_read, size_ - bytes_used_);
|
||||
// Only copy when destination address is different from the
|
||||
// current address in the buffer.
|
||||
if (_read_pos != data_ + bytes_used_) {
|
||||
memcpy (_read_pos, data_ + bytes_used_, to_copy);
|
||||
}
|
||||
|
||||
_read_pos += to_copy;
|
||||
_to_read -= to_copy;
|
||||
bytes_used_ += to_copy;
|
||||
// Try to get more space in the message to fill in.
|
||||
// If none is available, return.
|
||||
while (_to_read == 0) {
|
||||
// pass current address in the buffer
|
||||
const int rc =
|
||||
(static_cast<T *> (this)->*_next) (data_ + bytes_used_);
|
||||
if (rc != 0)
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void resize_buffer (std::size_t new_size_) ZMQ_FINAL
|
||||
{
|
||||
_allocator.resize (new_size_);
|
||||
}
|
||||
|
||||
protected:
|
||||
// Prototype of state machine action. Action should return false if
|
||||
// it is unable to push the data to the system.
|
||||
typedef int (T::*step_t) (unsigned char const *);
|
||||
|
||||
// This function should be called from derived class to read data
|
||||
// from the buffer and schedule next state machine action.
|
||||
void next_step (void *read_pos_, std::size_t to_read_, step_t next_)
|
||||
{
|
||||
_read_pos = static_cast<unsigned char *> (read_pos_);
|
||||
_to_read = to_read_;
|
||||
_next = next_;
|
||||
}
|
||||
|
||||
A &get_allocator () { return _allocator; }
|
||||
|
||||
private:
|
||||
// Next step. If set to NULL, it means that associated data stream
|
||||
// is dead. Note that there can be still data in the process in such
|
||||
// case.
|
||||
step_t _next;
|
||||
|
||||
// Where to store the read data.
|
||||
unsigned char *_read_pos;
|
||||
|
||||
// How much data to read before taking next step.
|
||||
std::size_t _to_read;
|
||||
|
||||
// The duffer for data to decode.
|
||||
A _allocator;
|
||||
unsigned char *_buf;
|
||||
|
||||
ZMQ_NON_COPYABLE_NOR_MOVABLE (decoder_base_t)
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
151
3rd/libzmq/src/decoder_allocators.cpp
Normal file
151
3rd/libzmq/src/decoder_allocators.cpp
Normal file
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "decoder_allocators.hpp"
|
||||
|
||||
#include "msg.hpp"
|
||||
|
||||
zmq::shared_message_memory_allocator::shared_message_memory_allocator (
|
||||
std::size_t bufsize_) :
|
||||
_buf (NULL),
|
||||
_buf_size (0),
|
||||
_max_size (bufsize_),
|
||||
_msg_content (NULL),
|
||||
_max_counters ((_max_size + msg_t::max_vsm_size - 1) / msg_t::max_vsm_size)
|
||||
{
|
||||
}
|
||||
|
||||
zmq::shared_message_memory_allocator::shared_message_memory_allocator (
|
||||
std::size_t bufsize_, std::size_t max_messages_) :
|
||||
_buf (NULL),
|
||||
_buf_size (0),
|
||||
_max_size (bufsize_),
|
||||
_msg_content (NULL),
|
||||
_max_counters (max_messages_)
|
||||
{
|
||||
}
|
||||
|
||||
zmq::shared_message_memory_allocator::~shared_message_memory_allocator ()
|
||||
{
|
||||
deallocate ();
|
||||
}
|
||||
|
||||
unsigned char *zmq::shared_message_memory_allocator::allocate ()
|
||||
{
|
||||
if (_buf) {
|
||||
// release reference count to couple lifetime to messages
|
||||
zmq::atomic_counter_t *c =
|
||||
reinterpret_cast<zmq::atomic_counter_t *> (_buf);
|
||||
|
||||
// if refcnt drops to 0, there are no message using the buffer
|
||||
// because either all messages have been closed or only vsm-messages
|
||||
// were created
|
||||
if (c->sub (1)) {
|
||||
// buffer is still in use as message data. "Release" it and create a new one
|
||||
// release pointer because we are going to create a new buffer
|
||||
release ();
|
||||
}
|
||||
}
|
||||
|
||||
// if buf != NULL it is not used by any message so we can re-use it for the next run
|
||||
if (!_buf) {
|
||||
// allocate memory for reference counters together with reception buffer
|
||||
std::size_t const allocationsize =
|
||||
_max_size + sizeof (zmq::atomic_counter_t)
|
||||
+ _max_counters * sizeof (zmq::msg_t::content_t);
|
||||
|
||||
_buf = static_cast<unsigned char *> (std::malloc (allocationsize));
|
||||
alloc_assert (_buf);
|
||||
|
||||
new (_buf) atomic_counter_t (1);
|
||||
} else {
|
||||
// release reference count to couple lifetime to messages
|
||||
zmq::atomic_counter_t *c =
|
||||
reinterpret_cast<zmq::atomic_counter_t *> (_buf);
|
||||
c->set (1);
|
||||
}
|
||||
|
||||
_buf_size = _max_size;
|
||||
_msg_content = reinterpret_cast<zmq::msg_t::content_t *> (
|
||||
_buf + sizeof (atomic_counter_t) + _max_size);
|
||||
return _buf + sizeof (zmq::atomic_counter_t);
|
||||
}
|
||||
|
||||
void zmq::shared_message_memory_allocator::deallocate ()
|
||||
{
|
||||
zmq::atomic_counter_t *c = reinterpret_cast<zmq::atomic_counter_t *> (_buf);
|
||||
if (_buf && !c->sub (1)) {
|
||||
std::free (_buf);
|
||||
}
|
||||
clear ();
|
||||
}
|
||||
|
||||
unsigned char *zmq::shared_message_memory_allocator::release ()
|
||||
{
|
||||
unsigned char *b = _buf;
|
||||
clear ();
|
||||
return b;
|
||||
}
|
||||
|
||||
void zmq::shared_message_memory_allocator::clear ()
|
||||
{
|
||||
_buf = NULL;
|
||||
_buf_size = 0;
|
||||
_msg_content = NULL;
|
||||
}
|
||||
|
||||
void zmq::shared_message_memory_allocator::inc_ref ()
|
||||
{
|
||||
(reinterpret_cast<zmq::atomic_counter_t *> (_buf))->add (1);
|
||||
}
|
||||
|
||||
void zmq::shared_message_memory_allocator::call_dec_ref (void *, void *hint_)
|
||||
{
|
||||
zmq_assert (hint_);
|
||||
unsigned char *buf = static_cast<unsigned char *> (hint_);
|
||||
zmq::atomic_counter_t *c = reinterpret_cast<zmq::atomic_counter_t *> (buf);
|
||||
|
||||
if (!c->sub (1)) {
|
||||
c->~atomic_counter_t ();
|
||||
std::free (buf);
|
||||
buf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::size_t zmq::shared_message_memory_allocator::size () const
|
||||
{
|
||||
return _buf_size;
|
||||
}
|
||||
|
||||
unsigned char *zmq::shared_message_memory_allocator::data ()
|
||||
{
|
||||
return _buf + sizeof (zmq::atomic_counter_t);
|
||||
}
|
||||
133
3rd/libzmq/src/decoder_allocators.hpp
Normal file
133
3rd/libzmq/src/decoder_allocators.hpp
Normal file
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ZMQ_DECODER_ALLOCATORS_HPP_INCLUDED__
|
||||
#define __ZMQ_DECODER_ALLOCATORS_HPP_INCLUDED__
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "atomic_counter.hpp"
|
||||
#include "msg.hpp"
|
||||
#include "err.hpp"
|
||||
|
||||
namespace zmq
|
||||
{
|
||||
// Static buffer policy.
|
||||
class c_single_allocator
|
||||
{
|
||||
public:
|
||||
explicit c_single_allocator (std::size_t bufsize_) :
|
||||
_buf_size (bufsize_),
|
||||
_buf (static_cast<unsigned char *> (std::malloc (_buf_size)))
|
||||
{
|
||||
alloc_assert (_buf);
|
||||
}
|
||||
|
||||
~c_single_allocator () { std::free (_buf); }
|
||||
|
||||
unsigned char *allocate () { return _buf; }
|
||||
|
||||
void deallocate () {}
|
||||
|
||||
std::size_t size () const { return _buf_size; }
|
||||
|
||||
// This buffer is fixed, size must not be changed
|
||||
void resize (std::size_t new_size_) { LIBZMQ_UNUSED (new_size_); }
|
||||
|
||||
private:
|
||||
std::size_t _buf_size;
|
||||
unsigned char *_buf;
|
||||
|
||||
ZMQ_NON_COPYABLE_NOR_MOVABLE (c_single_allocator)
|
||||
};
|
||||
|
||||
// This allocator allocates a reference counted buffer which is used by v2_decoder_t
|
||||
// to use zero-copy msg::init_data to create messages with memory from this buffer as
|
||||
// data storage.
|
||||
//
|
||||
// The buffer is allocated with a reference count of 1 to make sure that is is alive while
|
||||
// decoding messages. Otherwise, it is possible that e.g. the first message increases the count
|
||||
// from zero to one, gets passed to the user application, processed in the user thread and deleted
|
||||
// which would then deallocate the buffer. The drawback is that the buffer may be allocated longer
|
||||
// than necessary because it is only deleted when allocate is called the next time.
|
||||
class shared_message_memory_allocator
|
||||
{
|
||||
public:
|
||||
explicit shared_message_memory_allocator (std::size_t bufsize_);
|
||||
|
||||
// Create an allocator for a maximum number of messages
|
||||
shared_message_memory_allocator (std::size_t bufsize_,
|
||||
std::size_t max_messages_);
|
||||
|
||||
~shared_message_memory_allocator ();
|
||||
|
||||
// Allocate a new buffer
|
||||
//
|
||||
// This releases the current buffer to be bound to the lifetime of the messages
|
||||
// created on this buffer.
|
||||
unsigned char *allocate ();
|
||||
|
||||
// force deallocation of buffer.
|
||||
void deallocate ();
|
||||
|
||||
// Give up ownership of the buffer. The buffer's lifetime is now coupled to
|
||||
// the messages constructed on top of it.
|
||||
unsigned char *release ();
|
||||
|
||||
void inc_ref ();
|
||||
|
||||
static void call_dec_ref (void *, void *hint_);
|
||||
|
||||
std::size_t size () const;
|
||||
|
||||
// Return pointer to the first message data byte.
|
||||
unsigned char *data ();
|
||||
|
||||
// Return pointer to the first byte of the buffer.
|
||||
unsigned char *buffer () { return _buf; }
|
||||
|
||||
void resize (std::size_t new_size_) { _buf_size = new_size_; }
|
||||
|
||||
zmq::msg_t::content_t *provide_content () { return _msg_content; }
|
||||
|
||||
void advance_content () { _msg_content++; }
|
||||
|
||||
private:
|
||||
void clear ();
|
||||
|
||||
unsigned char *_buf;
|
||||
std::size_t _buf_size;
|
||||
const std::size_t _max_size;
|
||||
zmq::msg_t::content_t *_msg_content;
|
||||
std::size_t _max_counters;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
208
3rd/libzmq/src/devpoll.cpp
Normal file
208
3rd/libzmq/src/devpoll.cpp
Normal file
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "devpoll.hpp"
|
||||
#if defined ZMQ_IOTHREAD_POLLER_USE_DEVPOLL
|
||||
|
||||
#include <sys/devpoll.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#include <algorithm>
|
||||
|
||||
#include "devpoll.hpp"
|
||||
#include "err.hpp"
|
||||
#include "config.hpp"
|
||||
#include "i_poll_events.hpp"
|
||||
|
||||
zmq::devpoll_t::devpoll_t (const zmq::thread_ctx_t &ctx_) :
|
||||
worker_poller_base_t (ctx_)
|
||||
{
|
||||
devpoll_fd = open ("/dev/poll", O_RDWR);
|
||||
errno_assert (devpoll_fd != -1);
|
||||
}
|
||||
|
||||
zmq::devpoll_t::~devpoll_t ()
|
||||
{
|
||||
// Wait till the worker thread exits.
|
||||
stop_worker ();
|
||||
|
||||
close (devpoll_fd);
|
||||
}
|
||||
|
||||
void zmq::devpoll_t::devpoll_ctl (fd_t fd_, short events_)
|
||||
{
|
||||
struct pollfd pfd = {fd_, events_, 0};
|
||||
ssize_t rc = write (devpoll_fd, &pfd, sizeof pfd);
|
||||
zmq_assert (rc == sizeof pfd);
|
||||
}
|
||||
|
||||
zmq::devpoll_t::handle_t zmq::devpoll_t::add_fd (fd_t fd_,
|
||||
i_poll_events *reactor_)
|
||||
{
|
||||
check_thread ();
|
||||
// If the file descriptor table is too small expand it.
|
||||
fd_table_t::size_type sz = fd_table.size ();
|
||||
if (sz <= (fd_table_t::size_type) fd_) {
|
||||
fd_table.resize (fd_ + 1);
|
||||
while (sz != (fd_table_t::size_type) (fd_ + 1)) {
|
||||
fd_table[sz].valid = false;
|
||||
++sz;
|
||||
}
|
||||
}
|
||||
|
||||
zmq_assert (!fd_table[fd_].valid);
|
||||
|
||||
fd_table[fd_].events = 0;
|
||||
fd_table[fd_].reactor = reactor_;
|
||||
fd_table[fd_].valid = true;
|
||||
fd_table[fd_].accepted = false;
|
||||
|
||||
devpoll_ctl (fd_, 0);
|
||||
pending_list.push_back (fd_);
|
||||
|
||||
// Increase the load metric of the thread.
|
||||
adjust_load (1);
|
||||
|
||||
return fd_;
|
||||
}
|
||||
|
||||
void zmq::devpoll_t::rm_fd (handle_t handle_)
|
||||
{
|
||||
check_thread ();
|
||||
zmq_assert (fd_table[handle_].valid);
|
||||
|
||||
devpoll_ctl (handle_, POLLREMOVE);
|
||||
fd_table[handle_].valid = false;
|
||||
|
||||
// Decrease the load metric of the thread.
|
||||
adjust_load (-1);
|
||||
}
|
||||
|
||||
void zmq::devpoll_t::set_pollin (handle_t handle_)
|
||||
{
|
||||
check_thread ();
|
||||
devpoll_ctl (handle_, POLLREMOVE);
|
||||
fd_table[handle_].events |= POLLIN;
|
||||
devpoll_ctl (handle_, fd_table[handle_].events);
|
||||
}
|
||||
|
||||
void zmq::devpoll_t::reset_pollin (handle_t handle_)
|
||||
{
|
||||
check_thread ();
|
||||
devpoll_ctl (handle_, POLLREMOVE);
|
||||
fd_table[handle_].events &= ~((short) POLLIN);
|
||||
devpoll_ctl (handle_, fd_table[handle_].events);
|
||||
}
|
||||
|
||||
void zmq::devpoll_t::set_pollout (handle_t handle_)
|
||||
{
|
||||
check_thread ();
|
||||
devpoll_ctl (handle_, POLLREMOVE);
|
||||
fd_table[handle_].events |= POLLOUT;
|
||||
devpoll_ctl (handle_, fd_table[handle_].events);
|
||||
}
|
||||
|
||||
void zmq::devpoll_t::reset_pollout (handle_t handle_)
|
||||
{
|
||||
check_thread ();
|
||||
devpoll_ctl (handle_, POLLREMOVE);
|
||||
fd_table[handle_].events &= ~((short) POLLOUT);
|
||||
devpoll_ctl (handle_, fd_table[handle_].events);
|
||||
}
|
||||
|
||||
void zmq::devpoll_t::stop ()
|
||||
{
|
||||
check_thread ();
|
||||
}
|
||||
|
||||
int zmq::devpoll_t::max_fds ()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
void zmq::devpoll_t::loop ()
|
||||
{
|
||||
while (true) {
|
||||
struct pollfd ev_buf[max_io_events];
|
||||
struct dvpoll poll_req;
|
||||
|
||||
for (pending_list_t::size_type i = 0; i < pending_list.size (); i++)
|
||||
fd_table[pending_list[i]].accepted = true;
|
||||
pending_list.clear ();
|
||||
|
||||
// Execute any due timers.
|
||||
int timeout = (int) execute_timers ();
|
||||
|
||||
if (get_load () == 0) {
|
||||
if (timeout == 0)
|
||||
break;
|
||||
|
||||
// TODO sleep for timeout
|
||||
continue;
|
||||
}
|
||||
|
||||
// Wait for events.
|
||||
// On Solaris, we can retrieve no more then (OPEN_MAX - 1) events.
|
||||
poll_req.dp_fds = &ev_buf[0];
|
||||
#if defined ZMQ_HAVE_SOLARIS
|
||||
poll_req.dp_nfds = std::min ((int) max_io_events, OPEN_MAX - 1);
|
||||
#else
|
||||
poll_req.dp_nfds = max_io_events;
|
||||
#endif
|
||||
poll_req.dp_timeout = timeout ? timeout : -1;
|
||||
int n = ioctl (devpoll_fd, DP_POLL, &poll_req);
|
||||
if (n == -1 && errno == EINTR)
|
||||
continue;
|
||||
errno_assert (n != -1);
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
fd_entry_t *fd_ptr = &fd_table[ev_buf[i].fd];
|
||||
if (!fd_ptr->valid || !fd_ptr->accepted)
|
||||
continue;
|
||||
if (ev_buf[i].revents & (POLLERR | POLLHUP))
|
||||
fd_ptr->reactor->in_event ();
|
||||
if (!fd_ptr->valid || !fd_ptr->accepted)
|
||||
continue;
|
||||
if (ev_buf[i].revents & POLLOUT)
|
||||
fd_ptr->reactor->out_event ();
|
||||
if (!fd_ptr->valid || !fd_ptr->accepted)
|
||||
continue;
|
||||
if (ev_buf[i].revents & POLLIN)
|
||||
fd_ptr->reactor->in_event ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
101
3rd/libzmq/src/devpoll.hpp
Normal file
101
3rd/libzmq/src/devpoll.hpp
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ZMQ_DEVPOLL_HPP_INCLUDED__
|
||||
#define __ZMQ_DEVPOLL_HPP_INCLUDED__
|
||||
|
||||
// poller.hpp decides which polling mechanism to use.
|
||||
#include "poller.hpp"
|
||||
#if defined ZMQ_IOTHREAD_POLLER_USE_DEVPOLL
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "ctx.hpp"
|
||||
#include "fd.hpp"
|
||||
#include "thread.hpp"
|
||||
#include "poller_base.hpp"
|
||||
|
||||
namespace zmq
|
||||
{
|
||||
struct i_poll_events;
|
||||
|
||||
// Implements socket polling mechanism using the "/dev/poll" interface.
|
||||
|
||||
class devpoll_t ZMQ_FINAL : public worker_poller_base_t
|
||||
{
|
||||
public:
|
||||
typedef fd_t handle_t;
|
||||
|
||||
devpoll_t (const thread_ctx_t &ctx_);
|
||||
~devpoll_t () ZMQ_FINAL;
|
||||
|
||||
// "poller" concept.
|
||||
handle_t add_fd (fd_t fd_, zmq::i_poll_events *events_);
|
||||
void rm_fd (handle_t handle_);
|
||||
void set_pollin (handle_t handle_);
|
||||
void reset_pollin (handle_t handle_);
|
||||
void set_pollout (handle_t handle_);
|
||||
void reset_pollout (handle_t handle_);
|
||||
void stop ();
|
||||
|
||||
static int max_fds ();
|
||||
|
||||
private:
|
||||
// Main event loop.
|
||||
void loop () ZMQ_FINAL;
|
||||
|
||||
// File descriptor referring to "/dev/poll" pseudo-device.
|
||||
fd_t devpoll_fd;
|
||||
|
||||
struct fd_entry_t
|
||||
{
|
||||
short events;
|
||||
zmq::i_poll_events *reactor;
|
||||
bool valid;
|
||||
bool accepted;
|
||||
};
|
||||
|
||||
typedef std::vector<fd_entry_t> fd_table_t;
|
||||
fd_table_t fd_table;
|
||||
|
||||
typedef std::vector<fd_t> pending_list_t;
|
||||
pending_list_t pending_list;
|
||||
|
||||
// Pollset manipulation function.
|
||||
void devpoll_ctl (fd_t fd_, short events_);
|
||||
|
||||
ZMQ_NON_COPYABLE_NOR_MOVABLE (devpoll_t)
|
||||
};
|
||||
|
||||
typedef devpoll_t poller_t;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
169
3rd/libzmq/src/dgram.cpp
Normal file
169
3rd/libzmq/src/dgram.cpp
Normal file
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
Copyright (c) 2016 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "macros.hpp"
|
||||
#include "dgram.hpp"
|
||||
#include "pipe.hpp"
|
||||
#include "wire.hpp"
|
||||
#include "random.hpp"
|
||||
#include "likely.hpp"
|
||||
#include "err.hpp"
|
||||
|
||||
zmq::dgram_t::dgram_t (class ctx_t *parent_, uint32_t tid_, int sid_) :
|
||||
socket_base_t (parent_, tid_, sid_),
|
||||
_pipe (NULL),
|
||||
_last_in (NULL),
|
||||
_more_out (false)
|
||||
{
|
||||
options.type = ZMQ_DGRAM;
|
||||
options.raw_socket = true;
|
||||
}
|
||||
|
||||
zmq::dgram_t::~dgram_t ()
|
||||
{
|
||||
zmq_assert (!_pipe);
|
||||
}
|
||||
|
||||
void zmq::dgram_t::xattach_pipe (pipe_t *pipe_,
|
||||
bool subscribe_to_all_,
|
||||
bool locally_initiated_)
|
||||
{
|
||||
LIBZMQ_UNUSED (subscribe_to_all_);
|
||||
LIBZMQ_UNUSED (locally_initiated_);
|
||||
|
||||
zmq_assert (pipe_);
|
||||
|
||||
// ZMQ_DGRAM socket can only be connected to a single peer.
|
||||
// The socket rejects any further connection requests.
|
||||
if (_pipe == NULL)
|
||||
_pipe = pipe_;
|
||||
else
|
||||
pipe_->terminate (false);
|
||||
}
|
||||
|
||||
void zmq::dgram_t::xpipe_terminated (pipe_t *pipe_)
|
||||
{
|
||||
if (pipe_ == _pipe) {
|
||||
if (_last_in == _pipe) {
|
||||
_last_in = NULL;
|
||||
}
|
||||
_pipe = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void zmq::dgram_t::xread_activated (pipe_t *)
|
||||
{
|
||||
// There's just one pipe. No lists of active and inactive pipes.
|
||||
// There's nothing to do here.
|
||||
}
|
||||
|
||||
void zmq::dgram_t::xwrite_activated (pipe_t *)
|
||||
{
|
||||
// There's just one pipe. No lists of active and inactive pipes.
|
||||
// There's nothing to do here.
|
||||
}
|
||||
|
||||
int zmq::dgram_t::xsend (msg_t *msg_)
|
||||
{
|
||||
// If there's no out pipe, just drop it.
|
||||
if (!_pipe) {
|
||||
const int rc = msg_->close ();
|
||||
errno_assert (rc == 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// If this is the first part of the message it's the ID of the
|
||||
// peer to send the message to.
|
||||
if (!_more_out) {
|
||||
if (!(msg_->flags () & msg_t::more)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
// dgram messages are two part only, reject part if more is set
|
||||
if (msg_->flags () & msg_t::more) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Push the message into the pipe.
|
||||
if (!_pipe->write (msg_)) {
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(msg_->flags () & msg_t::more))
|
||||
_pipe->flush ();
|
||||
|
||||
// flip the more flag
|
||||
_more_out = !_more_out;
|
||||
|
||||
// Detach the message from the data buffer.
|
||||
const int rc = msg_->init ();
|
||||
errno_assert (rc == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int zmq::dgram_t::xrecv (msg_t *msg_)
|
||||
{
|
||||
// Deallocate old content of the message.
|
||||
int rc = msg_->close ();
|
||||
errno_assert (rc == 0);
|
||||
|
||||
if (!_pipe || !_pipe->read (msg_)) {
|
||||
// Initialise the output parameter to be a 0-byte message.
|
||||
rc = msg_->init ();
|
||||
errno_assert (rc == 0);
|
||||
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
_last_in = _pipe;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool zmq::dgram_t::xhas_in ()
|
||||
{
|
||||
if (!_pipe)
|
||||
return false;
|
||||
|
||||
return _pipe->check_read ();
|
||||
}
|
||||
|
||||
bool zmq::dgram_t::xhas_out ()
|
||||
{
|
||||
if (!_pipe)
|
||||
return false;
|
||||
|
||||
return _pipe->check_write ();
|
||||
}
|
||||
74
3rd/libzmq/src/dgram.hpp
Normal file
74
3rd/libzmq/src/dgram.hpp
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
Copyright (c) 2016 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ZMQ_DGRAM_HPP_INCLUDED__
|
||||
#define __ZMQ_DGRAM_HPP_INCLUDED__
|
||||
|
||||
#include "blob.hpp"
|
||||
#include "socket_base.hpp"
|
||||
#include "session_base.hpp"
|
||||
|
||||
namespace zmq
|
||||
{
|
||||
class ctx_t;
|
||||
class msg_t;
|
||||
class pipe_t;
|
||||
class io_thread_t;
|
||||
|
||||
class dgram_t ZMQ_FINAL : public socket_base_t
|
||||
{
|
||||
public:
|
||||
dgram_t (zmq::ctx_t *parent_, uint32_t tid_, int sid_);
|
||||
~dgram_t ();
|
||||
|
||||
// Overrides of functions from socket_base_t.
|
||||
void xattach_pipe (zmq::pipe_t *pipe_,
|
||||
bool subscribe_to_all_,
|
||||
bool locally_initiated_);
|
||||
int xsend (zmq::msg_t *msg_);
|
||||
int xrecv (zmq::msg_t *msg_);
|
||||
bool xhas_in ();
|
||||
bool xhas_out ();
|
||||
void xread_activated (zmq::pipe_t *pipe_);
|
||||
void xwrite_activated (zmq::pipe_t *pipe_);
|
||||
void xpipe_terminated (zmq::pipe_t *pipe_);
|
||||
|
||||
private:
|
||||
zmq::pipe_t *_pipe;
|
||||
|
||||
zmq::pipe_t *_last_in;
|
||||
|
||||
// If true, more outgoing message parts are expected.
|
||||
bool _more_out;
|
||||
|
||||
ZMQ_NON_COPYABLE_NOR_MOVABLE (dgram_t)
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
350
3rd/libzmq/src/dish.cpp
Normal file
350
3rd/libzmq/src/dish.cpp
Normal file
@@ -0,0 +1,350 @@
|
||||
/*
|
||||
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include <string.h>
|
||||
|
||||
#include "macros.hpp"
|
||||
#include "dish.hpp"
|
||||
#include "err.hpp"
|
||||
|
||||
zmq::dish_t::dish_t (class ctx_t *parent_, uint32_t tid_, int sid_) :
|
||||
socket_base_t (parent_, tid_, sid_, true),
|
||||
_has_message (false)
|
||||
{
|
||||
options.type = ZMQ_DISH;
|
||||
|
||||
// When socket is being closed down we don't want to wait till pending
|
||||
// subscription commands are sent to the wire.
|
||||
options.linger.store (0);
|
||||
|
||||
const int rc = _message.init ();
|
||||
errno_assert (rc == 0);
|
||||
}
|
||||
|
||||
zmq::dish_t::~dish_t ()
|
||||
{
|
||||
const int rc = _message.close ();
|
||||
errno_assert (rc == 0);
|
||||
}
|
||||
|
||||
void zmq::dish_t::xattach_pipe (pipe_t *pipe_,
|
||||
bool subscribe_to_all_,
|
||||
bool locally_initiated_)
|
||||
{
|
||||
LIBZMQ_UNUSED (subscribe_to_all_);
|
||||
LIBZMQ_UNUSED (locally_initiated_);
|
||||
|
||||
zmq_assert (pipe_);
|
||||
_fq.attach (pipe_);
|
||||
_dist.attach (pipe_);
|
||||
|
||||
// Send all the cached subscriptions to the new upstream peer.
|
||||
send_subscriptions (pipe_);
|
||||
}
|
||||
|
||||
void zmq::dish_t::xread_activated (pipe_t *pipe_)
|
||||
{
|
||||
_fq.activated (pipe_);
|
||||
}
|
||||
|
||||
void zmq::dish_t::xwrite_activated (pipe_t *pipe_)
|
||||
{
|
||||
_dist.activated (pipe_);
|
||||
}
|
||||
|
||||
void zmq::dish_t::xpipe_terminated (pipe_t *pipe_)
|
||||
{
|
||||
_fq.pipe_terminated (pipe_);
|
||||
_dist.pipe_terminated (pipe_);
|
||||
}
|
||||
|
||||
void zmq::dish_t::xhiccuped (pipe_t *pipe_)
|
||||
{
|
||||
// Send all the cached subscriptions to the hiccuped pipe.
|
||||
send_subscriptions (pipe_);
|
||||
}
|
||||
|
||||
int zmq::dish_t::xjoin (const char *group_)
|
||||
{
|
||||
const std::string group = std::string (group_);
|
||||
|
||||
if (group.length () > ZMQ_GROUP_MAX_LENGTH) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// User cannot join same group twice
|
||||
if (!_subscriptions.insert (group).second) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
msg_t msg;
|
||||
int rc = msg.init_join ();
|
||||
errno_assert (rc == 0);
|
||||
|
||||
rc = msg.set_group (group_);
|
||||
errno_assert (rc == 0);
|
||||
|
||||
int err = 0;
|
||||
rc = _dist.send_to_all (&msg);
|
||||
if (rc != 0)
|
||||
err = errno;
|
||||
const int rc2 = msg.close ();
|
||||
errno_assert (rc2 == 0);
|
||||
if (rc != 0)
|
||||
errno = err;
|
||||
return rc;
|
||||
}
|
||||
|
||||
int zmq::dish_t::xleave (const char *group_)
|
||||
{
|
||||
const std::string group = std::string (group_);
|
||||
|
||||
if (group.length () > ZMQ_GROUP_MAX_LENGTH) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (0 == _subscriptions.erase (group)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
msg_t msg;
|
||||
int rc = msg.init_leave ();
|
||||
errno_assert (rc == 0);
|
||||
|
||||
rc = msg.set_group (group_);
|
||||
errno_assert (rc == 0);
|
||||
|
||||
int err = 0;
|
||||
rc = _dist.send_to_all (&msg);
|
||||
if (rc != 0)
|
||||
err = errno;
|
||||
const int rc2 = msg.close ();
|
||||
errno_assert (rc2 == 0);
|
||||
if (rc != 0)
|
||||
errno = err;
|
||||
return rc;
|
||||
}
|
||||
|
||||
int zmq::dish_t::xsend (msg_t *msg_)
|
||||
{
|
||||
LIBZMQ_UNUSED (msg_);
|
||||
errno = ENOTSUP;
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool zmq::dish_t::xhas_out ()
|
||||
{
|
||||
// Subscription can be added/removed anytime.
|
||||
return true;
|
||||
}
|
||||
|
||||
int zmq::dish_t::xrecv (msg_t *msg_)
|
||||
{
|
||||
// If there's already a message prepared by a previous call to zmq_poll,
|
||||
// return it straight ahead.
|
||||
if (_has_message) {
|
||||
const int rc = msg_->move (_message);
|
||||
errno_assert (rc == 0);
|
||||
_has_message = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return xxrecv (msg_);
|
||||
}
|
||||
|
||||
int zmq::dish_t::xxrecv (msg_t *msg_)
|
||||
{
|
||||
do {
|
||||
// Get a message using fair queueing algorithm.
|
||||
const int rc = _fq.recv (msg_);
|
||||
|
||||
// If there's no message available, return immediately.
|
||||
// The same when error occurs.
|
||||
if (rc != 0)
|
||||
return -1;
|
||||
|
||||
// Skip non matching messages
|
||||
} while (0 == _subscriptions.count (std::string (msg_->group ())));
|
||||
|
||||
// Found a matching message
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool zmq::dish_t::xhas_in ()
|
||||
{
|
||||
// If there's already a message prepared by a previous call to zmq_poll,
|
||||
// return straight ahead.
|
||||
if (_has_message)
|
||||
return true;
|
||||
|
||||
const int rc = xxrecv (&_message);
|
||||
if (rc != 0) {
|
||||
errno_assert (errno == EAGAIN);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Matching message found
|
||||
_has_message = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void zmq::dish_t::send_subscriptions (pipe_t *pipe_)
|
||||
{
|
||||
for (subscriptions_t::iterator it = _subscriptions.begin (),
|
||||
end = _subscriptions.end ();
|
||||
it != end; ++it) {
|
||||
msg_t msg;
|
||||
int rc = msg.init_join ();
|
||||
errno_assert (rc == 0);
|
||||
|
||||
rc = msg.set_group (it->c_str ());
|
||||
errno_assert (rc == 0);
|
||||
|
||||
// Send it to the pipe.
|
||||
pipe_->write (&msg);
|
||||
}
|
||||
|
||||
pipe_->flush ();
|
||||
}
|
||||
|
||||
zmq::dish_session_t::dish_session_t (io_thread_t *io_thread_,
|
||||
bool connect_,
|
||||
socket_base_t *socket_,
|
||||
const options_t &options_,
|
||||
address_t *addr_) :
|
||||
session_base_t (io_thread_, connect_, socket_, options_, addr_),
|
||||
_state (group)
|
||||
{
|
||||
}
|
||||
|
||||
zmq::dish_session_t::~dish_session_t ()
|
||||
{
|
||||
}
|
||||
|
||||
int zmq::dish_session_t::push_msg (msg_t *msg_)
|
||||
{
|
||||
if (_state == group) {
|
||||
if ((msg_->flags () & msg_t::more) != msg_t::more) {
|
||||
errno = EFAULT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (msg_->size () > ZMQ_GROUP_MAX_LENGTH) {
|
||||
errno = EFAULT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
_group_msg = *msg_;
|
||||
_state = body;
|
||||
|
||||
const int rc = msg_->init ();
|
||||
errno_assert (rc == 0);
|
||||
return 0;
|
||||
}
|
||||
const char *group_setting = msg_->group ();
|
||||
int rc;
|
||||
if (group_setting[0] != 0)
|
||||
goto has_group;
|
||||
|
||||
// Set the message group
|
||||
rc = msg_->set_group (static_cast<char *> (_group_msg.data ()),
|
||||
_group_msg.size ());
|
||||
errno_assert (rc == 0);
|
||||
|
||||
// We set the group, so we don't need the group_msg anymore
|
||||
rc = _group_msg.close ();
|
||||
errno_assert (rc == 0);
|
||||
has_group:
|
||||
// Thread safe socket doesn't support multipart messages
|
||||
if ((msg_->flags () & msg_t::more) == msg_t::more) {
|
||||
errno = EFAULT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Push message to dish socket
|
||||
rc = session_base_t::push_msg (msg_);
|
||||
|
||||
if (rc == 0)
|
||||
_state = group;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int zmq::dish_session_t::pull_msg (msg_t *msg_)
|
||||
{
|
||||
int rc = session_base_t::pull_msg (msg_);
|
||||
|
||||
if (rc != 0)
|
||||
return rc;
|
||||
|
||||
if (!msg_->is_join () && !msg_->is_leave ())
|
||||
return rc;
|
||||
|
||||
const int group_length = static_cast<int> (strlen (msg_->group ()));
|
||||
|
||||
msg_t command;
|
||||
int offset;
|
||||
|
||||
if (msg_->is_join ()) {
|
||||
rc = command.init_size (group_length + 5);
|
||||
errno_assert (rc == 0);
|
||||
offset = 5;
|
||||
memcpy (command.data (), "\4JOIN", 5);
|
||||
} else {
|
||||
rc = command.init_size (group_length + 6);
|
||||
errno_assert (rc == 0);
|
||||
offset = 6;
|
||||
memcpy (command.data (), "\5LEAVE", 6);
|
||||
}
|
||||
|
||||
command.set_flags (msg_t::command);
|
||||
char *command_data = static_cast<char *> (command.data ());
|
||||
|
||||
// Copy the group
|
||||
memcpy (command_data + offset, msg_->group (), group_length);
|
||||
|
||||
// Close the join message
|
||||
rc = msg_->close ();
|
||||
errno_assert (rc == 0);
|
||||
|
||||
*msg_ = command;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void zmq::dish_session_t::reset ()
|
||||
{
|
||||
session_base_t::reset ();
|
||||
_state = group;
|
||||
}
|
||||
121
3rd/libzmq/src/dish.hpp
Normal file
121
3rd/libzmq/src/dish.hpp
Normal file
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ZMQ_DISH_HPP_INCLUDED__
|
||||
#define __ZMQ_DISH_HPP_INCLUDED__
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "socket_base.hpp"
|
||||
#include "session_base.hpp"
|
||||
#include "dist.hpp"
|
||||
#include "fq.hpp"
|
||||
#include "msg.hpp"
|
||||
|
||||
namespace zmq
|
||||
{
|
||||
class ctx_t;
|
||||
class pipe_t;
|
||||
class io_thread_t;
|
||||
|
||||
class dish_t ZMQ_FINAL : public socket_base_t
|
||||
{
|
||||
public:
|
||||
dish_t (zmq::ctx_t *parent_, uint32_t tid_, int sid_);
|
||||
~dish_t ();
|
||||
|
||||
protected:
|
||||
// Overrides of functions from socket_base_t.
|
||||
void xattach_pipe (zmq::pipe_t *pipe_,
|
||||
bool subscribe_to_all_,
|
||||
bool locally_initiated_);
|
||||
int xsend (zmq::msg_t *msg_);
|
||||
bool xhas_out ();
|
||||
int xrecv (zmq::msg_t *msg_);
|
||||
bool xhas_in ();
|
||||
void xread_activated (zmq::pipe_t *pipe_);
|
||||
void xwrite_activated (zmq::pipe_t *pipe_);
|
||||
void xhiccuped (pipe_t *pipe_);
|
||||
void xpipe_terminated (zmq::pipe_t *pipe_);
|
||||
int xjoin (const char *group_);
|
||||
int xleave (const char *group_);
|
||||
|
||||
private:
|
||||
int xxrecv (zmq::msg_t *msg_);
|
||||
|
||||
// Send subscriptions to a pipe
|
||||
void send_subscriptions (pipe_t *pipe_);
|
||||
|
||||
// Fair queueing object for inbound pipes.
|
||||
fq_t _fq;
|
||||
|
||||
// Object for distributing the subscriptions upstream.
|
||||
dist_t _dist;
|
||||
|
||||
// The repository of subscriptions.
|
||||
typedef std::set<std::string> subscriptions_t;
|
||||
subscriptions_t _subscriptions;
|
||||
|
||||
// If true, 'message' contains a matching message to return on the
|
||||
// next recv call.
|
||||
bool _has_message;
|
||||
msg_t _message;
|
||||
|
||||
ZMQ_NON_COPYABLE_NOR_MOVABLE (dish_t)
|
||||
};
|
||||
|
||||
class dish_session_t ZMQ_FINAL : public session_base_t
|
||||
{
|
||||
public:
|
||||
dish_session_t (zmq::io_thread_t *io_thread_,
|
||||
bool connect_,
|
||||
zmq::socket_base_t *socket_,
|
||||
const options_t &options_,
|
||||
address_t *addr_);
|
||||
~dish_session_t ();
|
||||
|
||||
// Overrides of the functions from session_base_t.
|
||||
int push_msg (msg_t *msg_);
|
||||
int pull_msg (msg_t *msg_);
|
||||
void reset ();
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
group,
|
||||
body
|
||||
} _state;
|
||||
|
||||
msg_t _group_msg;
|
||||
|
||||
ZMQ_NON_COPYABLE_NOR_MOVABLE (dish_session_t)
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
237
3rd/libzmq/src/dist.cpp
Normal file
237
3rd/libzmq/src/dist.cpp
Normal file
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "dist.hpp"
|
||||
#include "pipe.hpp"
|
||||
#include "err.hpp"
|
||||
#include "msg.hpp"
|
||||
#include "likely.hpp"
|
||||
|
||||
zmq::dist_t::dist_t () :
|
||||
_matching (0),
|
||||
_active (0),
|
||||
_eligible (0),
|
||||
_more (false)
|
||||
{
|
||||
}
|
||||
|
||||
zmq::dist_t::~dist_t ()
|
||||
{
|
||||
zmq_assert (_pipes.empty ());
|
||||
}
|
||||
|
||||
void zmq::dist_t::attach (pipe_t *pipe_)
|
||||
{
|
||||
// If we are in the middle of sending a message, we'll add new pipe
|
||||
// into the list of eligible pipes. Otherwise we add it to the list
|
||||
// of active pipes.
|
||||
if (_more) {
|
||||
_pipes.push_back (pipe_);
|
||||
_pipes.swap (_eligible, _pipes.size () - 1);
|
||||
_eligible++;
|
||||
} else {
|
||||
_pipes.push_back (pipe_);
|
||||
_pipes.swap (_active, _pipes.size () - 1);
|
||||
_active++;
|
||||
_eligible++;
|
||||
}
|
||||
}
|
||||
|
||||
void zmq::dist_t::match (pipe_t *pipe_)
|
||||
{
|
||||
// If pipe is already matching do nothing.
|
||||
if (_pipes.index (pipe_) < _matching)
|
||||
return;
|
||||
|
||||
// If the pipe isn't eligible, ignore it.
|
||||
if (_pipes.index (pipe_) >= _eligible)
|
||||
return;
|
||||
|
||||
// Mark the pipe as matching.
|
||||
_pipes.swap (_pipes.index (pipe_), _matching);
|
||||
_matching++;
|
||||
}
|
||||
|
||||
void zmq::dist_t::reverse_match ()
|
||||
{
|
||||
const pipes_t::size_type prev_matching = _matching;
|
||||
|
||||
// Reset matching to 0
|
||||
unmatch ();
|
||||
|
||||
// Mark all matching pipes as not matching and vice-versa.
|
||||
// To do this, push all pipes that are eligible but not
|
||||
// matched - i.e. between "matching" and "eligible" -
|
||||
// to the beginning of the queue.
|
||||
for (pipes_t::size_type i = prev_matching; i < _eligible; ++i) {
|
||||
_pipes.swap (i, _matching++);
|
||||
}
|
||||
}
|
||||
|
||||
void zmq::dist_t::unmatch ()
|
||||
{
|
||||
_matching = 0;
|
||||
}
|
||||
|
||||
void zmq::dist_t::pipe_terminated (pipe_t *pipe_)
|
||||
{
|
||||
// Remove the pipe from the list; adjust number of matching, active and/or
|
||||
// eligible pipes accordingly.
|
||||
if (_pipes.index (pipe_) < _matching) {
|
||||
_pipes.swap (_pipes.index (pipe_), _matching - 1);
|
||||
_matching--;
|
||||
}
|
||||
if (_pipes.index (pipe_) < _active) {
|
||||
_pipes.swap (_pipes.index (pipe_), _active - 1);
|
||||
_active--;
|
||||
}
|
||||
if (_pipes.index (pipe_) < _eligible) {
|
||||
_pipes.swap (_pipes.index (pipe_), _eligible - 1);
|
||||
_eligible--;
|
||||
}
|
||||
|
||||
_pipes.erase (pipe_);
|
||||
}
|
||||
|
||||
void zmq::dist_t::activated (pipe_t *pipe_)
|
||||
{
|
||||
// Move the pipe from passive to eligible state.
|
||||
if (_eligible < _pipes.size ()) {
|
||||
_pipes.swap (_pipes.index (pipe_), _eligible);
|
||||
_eligible++;
|
||||
}
|
||||
|
||||
// If there's no message being sent at the moment, move it to
|
||||
// the active state.
|
||||
if (!_more && _active < _pipes.size ()) {
|
||||
_pipes.swap (_eligible - 1, _active);
|
||||
_active++;
|
||||
}
|
||||
}
|
||||
|
||||
int zmq::dist_t::send_to_all (msg_t *msg_)
|
||||
{
|
||||
_matching = _active;
|
||||
return send_to_matching (msg_);
|
||||
}
|
||||
|
||||
int zmq::dist_t::send_to_matching (msg_t *msg_)
|
||||
{
|
||||
// Is this end of a multipart message?
|
||||
const bool msg_more = (msg_->flags () & msg_t::more) != 0;
|
||||
|
||||
// Push the message to matching pipes.
|
||||
distribute (msg_);
|
||||
|
||||
// If multipart message is fully sent, activate all the eligible pipes.
|
||||
if (!msg_more)
|
||||
_active = _eligible;
|
||||
|
||||
_more = msg_more;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void zmq::dist_t::distribute (msg_t *msg_)
|
||||
{
|
||||
// If there are no matching pipes available, simply drop the message.
|
||||
if (_matching == 0) {
|
||||
int rc = msg_->close ();
|
||||
errno_assert (rc == 0);
|
||||
rc = msg_->init ();
|
||||
errno_assert (rc == 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg_->is_vsm ()) {
|
||||
for (pipes_t::size_type i = 0; i < _matching;) {
|
||||
if (!write (_pipes[i], msg_)) {
|
||||
// Use same index again because entry will have been removed.
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
int rc = msg_->init ();
|
||||
errno_assert (rc == 0);
|
||||
return;
|
||||
}
|
||||
|
||||
// Add matching-1 references to the message. We already hold one reference,
|
||||
// that's why -1.
|
||||
msg_->add_refs (static_cast<int> (_matching) - 1);
|
||||
|
||||
// Push copy of the message to each matching pipe.
|
||||
int failed = 0;
|
||||
for (pipes_t::size_type i = 0; i < _matching;) {
|
||||
if (!write (_pipes[i], msg_)) {
|
||||
++failed;
|
||||
// Use same index again because entry will have been removed.
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
if (unlikely (failed))
|
||||
msg_->rm_refs (failed);
|
||||
|
||||
// Detach the original message from the data buffer. Note that we don't
|
||||
// close the message. That's because we've already used all the references.
|
||||
const int rc = msg_->init ();
|
||||
errno_assert (rc == 0);
|
||||
}
|
||||
|
||||
bool zmq::dist_t::has_out ()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool zmq::dist_t::write (pipe_t *pipe_, msg_t *msg_)
|
||||
{
|
||||
if (!pipe_->write (msg_)) {
|
||||
_pipes.swap (_pipes.index (pipe_), _matching - 1);
|
||||
_matching--;
|
||||
_pipes.swap (_pipes.index (pipe_), _active - 1);
|
||||
_active--;
|
||||
_pipes.swap (_active, _eligible - 1);
|
||||
_eligible--;
|
||||
return false;
|
||||
}
|
||||
if (!(msg_->flags () & msg_t::more))
|
||||
pipe_->flush ();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool zmq::dist_t::check_hwm ()
|
||||
{
|
||||
for (pipes_t::size_type i = 0; i < _matching; ++i)
|
||||
if (!_pipes[i]->check_hwm ())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
115
3rd/libzmq/src/dist.hpp
Normal file
115
3rd/libzmq/src/dist.hpp
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ZMQ_DIST_HPP_INCLUDED__
|
||||
#define __ZMQ_DIST_HPP_INCLUDED__
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "array.hpp"
|
||||
#include "macros.hpp"
|
||||
|
||||
namespace zmq
|
||||
{
|
||||
class pipe_t;
|
||||
class msg_t;
|
||||
|
||||
// Class manages a set of outbound pipes. It sends each messages to
|
||||
// each of them.
|
||||
class dist_t
|
||||
{
|
||||
public:
|
||||
dist_t ();
|
||||
~dist_t ();
|
||||
|
||||
// Adds the pipe to the distributor object.
|
||||
void attach (zmq::pipe_t *pipe_);
|
||||
|
||||
// Activates pipe that have previously reached high watermark.
|
||||
void activated (zmq::pipe_t *pipe_);
|
||||
|
||||
// Mark the pipe as matching. Subsequent call to send_to_matching
|
||||
// will send message also to this pipe.
|
||||
void match (zmq::pipe_t *pipe_);
|
||||
|
||||
// Marks all pipes that are not matched as matched and vice-versa.
|
||||
void reverse_match ();
|
||||
|
||||
// Mark all pipes as non-matching.
|
||||
void unmatch ();
|
||||
|
||||
// Removes the pipe from the distributor object.
|
||||
void pipe_terminated (zmq::pipe_t *pipe_);
|
||||
|
||||
// Send the message to the matching outbound pipes.
|
||||
int send_to_matching (zmq::msg_t *msg_);
|
||||
|
||||
// Send the message to all the outbound pipes.
|
||||
int send_to_all (zmq::msg_t *msg_);
|
||||
|
||||
static bool has_out ();
|
||||
|
||||
// check HWM of all pipes matching
|
||||
bool check_hwm ();
|
||||
|
||||
private:
|
||||
// Write the message to the pipe. Make the pipe inactive if writing
|
||||
// fails. In such a case false is returned.
|
||||
bool write (zmq::pipe_t *pipe_, zmq::msg_t *msg_);
|
||||
|
||||
// Put the message to all active pipes.
|
||||
void distribute (zmq::msg_t *msg_);
|
||||
|
||||
// List of outbound pipes.
|
||||
typedef array_t<zmq::pipe_t, 2> pipes_t;
|
||||
pipes_t _pipes;
|
||||
|
||||
// Number of all the pipes to send the next message to.
|
||||
pipes_t::size_type _matching;
|
||||
|
||||
// Number of active pipes. All the active pipes are located at the
|
||||
// beginning of the pipes array. These are the pipes the messages
|
||||
// can be sent to at the moment.
|
||||
pipes_t::size_type _active;
|
||||
|
||||
// Number of pipes eligible for sending messages to. This includes all
|
||||
// the active pipes plus all the pipes that we can in theory send
|
||||
// messages to (the HWM is not yet reached), but sending a message
|
||||
// to them would result in partial message being delivered, ie. message
|
||||
// with initial parts missing.
|
||||
pipes_t::size_type _eligible;
|
||||
|
||||
// True if last we are in the middle of a multipart message.
|
||||
bool _more;
|
||||
|
||||
ZMQ_NON_COPYABLE_NOR_MOVABLE (dist_t)
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
178
3rd/libzmq/src/encoder.hpp
Normal file
178
3rd/libzmq/src/encoder.hpp
Normal file
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ZMQ_ENCODER_HPP_INCLUDED__
|
||||
#define __ZMQ_ENCODER_HPP_INCLUDED__
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <algorithm>
|
||||
|
||||
#include "err.hpp"
|
||||
#include "i_encoder.hpp"
|
||||
#include "msg.hpp"
|
||||
|
||||
namespace zmq
|
||||
{
|
||||
// Helper base class for encoders. It implements the state machine that
|
||||
// fills the outgoing buffer. Derived classes should implement individual
|
||||
// state machine actions.
|
||||
|
||||
template <typename T> class encoder_base_t : public i_encoder
|
||||
{
|
||||
public:
|
||||
explicit encoder_base_t (size_t bufsize_) :
|
||||
_write_pos (0),
|
||||
_to_write (0),
|
||||
_next (NULL),
|
||||
_new_msg_flag (false),
|
||||
_buf_size (bufsize_),
|
||||
_buf (static_cast<unsigned char *> (malloc (bufsize_))),
|
||||
_in_progress (NULL)
|
||||
{
|
||||
alloc_assert (_buf);
|
||||
}
|
||||
|
||||
~encoder_base_t () ZMQ_OVERRIDE { free (_buf); }
|
||||
|
||||
// The function returns a batch of binary data. The data
|
||||
// are filled to a supplied buffer. If no buffer is supplied (data_
|
||||
// points to NULL) decoder object will provide buffer of its own.
|
||||
size_t encode (unsigned char **data_, size_t size_) ZMQ_FINAL
|
||||
{
|
||||
unsigned char *buffer = !*data_ ? _buf : *data_;
|
||||
const size_t buffersize = !*data_ ? _buf_size : size_;
|
||||
|
||||
if (in_progress () == NULL)
|
||||
return 0;
|
||||
|
||||
size_t pos = 0;
|
||||
while (pos < buffersize) {
|
||||
// If there are no more data to return, run the state machine.
|
||||
// If there are still no data, return what we already have
|
||||
// in the buffer.
|
||||
if (!_to_write) {
|
||||
if (_new_msg_flag) {
|
||||
int rc = _in_progress->close ();
|
||||
errno_assert (rc == 0);
|
||||
rc = _in_progress->init ();
|
||||
errno_assert (rc == 0);
|
||||
_in_progress = NULL;
|
||||
break;
|
||||
}
|
||||
(static_cast<T *> (this)->*_next) ();
|
||||
}
|
||||
|
||||
// If there are no data in the buffer yet and we are able to
|
||||
// fill whole buffer in a single go, let's use zero-copy.
|
||||
// There's no disadvantage to it as we cannot stuck multiple
|
||||
// messages into the buffer anyway. Note that subsequent
|
||||
// write(s) are non-blocking, thus each single write writes
|
||||
// at most SO_SNDBUF bytes at once not depending on how large
|
||||
// is the chunk returned from here.
|
||||
// As a consequence, large messages being sent won't block
|
||||
// other engines running in the same I/O thread for excessive
|
||||
// amounts of time.
|
||||
if (!pos && !*data_ && _to_write >= buffersize) {
|
||||
*data_ = _write_pos;
|
||||
pos = _to_write;
|
||||
_write_pos = NULL;
|
||||
_to_write = 0;
|
||||
return pos;
|
||||
}
|
||||
|
||||
// Copy data to the buffer. If the buffer is full, return.
|
||||
const size_t to_copy = std::min (_to_write, buffersize - pos);
|
||||
memcpy (buffer + pos, _write_pos, to_copy);
|
||||
pos += to_copy;
|
||||
_write_pos += to_copy;
|
||||
_to_write -= to_copy;
|
||||
}
|
||||
|
||||
*data_ = buffer;
|
||||
return pos;
|
||||
}
|
||||
|
||||
void load_msg (msg_t *msg_) ZMQ_FINAL
|
||||
{
|
||||
zmq_assert (in_progress () == NULL);
|
||||
_in_progress = msg_;
|
||||
(static_cast<T *> (this)->*_next) ();
|
||||
}
|
||||
|
||||
protected:
|
||||
// Prototype of state machine action.
|
||||
typedef void (T::*step_t) ();
|
||||
|
||||
// This function should be called from derived class to write the data
|
||||
// to the buffer and schedule next state machine action.
|
||||
void next_step (void *write_pos_,
|
||||
size_t to_write_,
|
||||
step_t next_,
|
||||
bool new_msg_flag_)
|
||||
{
|
||||
_write_pos = static_cast<unsigned char *> (write_pos_);
|
||||
_to_write = to_write_;
|
||||
_next = next_;
|
||||
_new_msg_flag = new_msg_flag_;
|
||||
}
|
||||
|
||||
msg_t *in_progress () { return _in_progress; }
|
||||
|
||||
private:
|
||||
// Where to get the data to write from.
|
||||
unsigned char *_write_pos;
|
||||
|
||||
// How much data to write before next step should be executed.
|
||||
size_t _to_write;
|
||||
|
||||
// Next step. If set to NULL, it means that associated data stream
|
||||
// is dead.
|
||||
step_t _next;
|
||||
|
||||
bool _new_msg_flag;
|
||||
|
||||
// The buffer for encoded data.
|
||||
const size_t _buf_size;
|
||||
unsigned char *const _buf;
|
||||
|
||||
msg_t *_in_progress;
|
||||
|
||||
ZMQ_NON_COPYABLE_NOR_MOVABLE (encoder_base_t)
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
44
3rd/libzmq/src/endpoint.cpp
Normal file
44
3rd/libzmq/src/endpoint.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "endpoint.hpp"
|
||||
|
||||
zmq::endpoint_uri_pair_t
|
||||
zmq::make_unconnected_connect_endpoint_pair (const std::string &endpoint_)
|
||||
{
|
||||
return endpoint_uri_pair_t (std::string (), endpoint_,
|
||||
endpoint_type_connect);
|
||||
}
|
||||
|
||||
zmq::endpoint_uri_pair_t
|
||||
zmq::make_unconnected_bind_endpoint_pair (const std::string &endpoint_)
|
||||
{
|
||||
return endpoint_uri_pair_t (endpoint_, std::string (), endpoint_type_bind);
|
||||
}
|
||||
72
3rd/libzmq/src/endpoint.hpp
Normal file
72
3rd/libzmq/src/endpoint.hpp
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ZMQ_ENDPOINT_HPP_INCLUDED__
|
||||
#define __ZMQ_ENDPOINT_HPP_INCLUDED__
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace zmq
|
||||
{
|
||||
enum endpoint_type_t
|
||||
{
|
||||
endpoint_type_none, // a connection-less endpoint
|
||||
endpoint_type_bind, // a connection-oriented bind endpoint
|
||||
endpoint_type_connect // a connection-oriented connect endpoint
|
||||
};
|
||||
|
||||
struct endpoint_uri_pair_t
|
||||
{
|
||||
endpoint_uri_pair_t () : local_type (endpoint_type_none) {}
|
||||
endpoint_uri_pair_t (const std::string &local,
|
||||
const std::string &remote,
|
||||
endpoint_type_t local_type) :
|
||||
local (local),
|
||||
remote (remote),
|
||||
local_type (local_type)
|
||||
{
|
||||
}
|
||||
|
||||
const std::string &identifier () const
|
||||
{
|
||||
return local_type == endpoint_type_bind ? local : remote;
|
||||
}
|
||||
|
||||
std::string local, remote;
|
||||
endpoint_type_t local_type;
|
||||
};
|
||||
|
||||
endpoint_uri_pair_t
|
||||
make_unconnected_connect_endpoint_pair (const std::string &endpoint_);
|
||||
|
||||
endpoint_uri_pair_t
|
||||
make_unconnected_bind_endpoint_pair (const std::string &endpoint_);
|
||||
}
|
||||
|
||||
#endif
|
||||
218
3rd/libzmq/src/epoll.cpp
Normal file
218
3rd/libzmq/src/epoll.cpp
Normal file
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#if defined ZMQ_IOTHREAD_POLLER_USE_EPOLL
|
||||
#include "epoll.hpp"
|
||||
|
||||
#if !defined ZMQ_HAVE_WINDOWS
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <algorithm>
|
||||
#include <new>
|
||||
|
||||
#include "macros.hpp"
|
||||
#include "err.hpp"
|
||||
#include "config.hpp"
|
||||
#include "i_poll_events.hpp"
|
||||
|
||||
#ifdef ZMQ_HAVE_WINDOWS
|
||||
const zmq::epoll_t::epoll_fd_t zmq::epoll_t::epoll_retired_fd =
|
||||
INVALID_HANDLE_VALUE;
|
||||
#endif
|
||||
|
||||
zmq::epoll_t::epoll_t (const zmq::thread_ctx_t &ctx_) :
|
||||
worker_poller_base_t (ctx_)
|
||||
{
|
||||
#ifdef ZMQ_IOTHREAD_POLLER_USE_EPOLL_CLOEXEC
|
||||
// Setting this option result in sane behaviour when exec() functions
|
||||
// are used. Old sockets are closed and don't block TCP ports, avoid
|
||||
// leaks, etc.
|
||||
_epoll_fd = epoll_create1 (EPOLL_CLOEXEC);
|
||||
#else
|
||||
_epoll_fd = epoll_create (1);
|
||||
#endif
|
||||
errno_assert (_epoll_fd != epoll_retired_fd);
|
||||
}
|
||||
|
||||
zmq::epoll_t::~epoll_t ()
|
||||
{
|
||||
// Wait till the worker thread exits.
|
||||
stop_worker ();
|
||||
|
||||
#ifdef ZMQ_HAVE_WINDOWS
|
||||
epoll_close (_epoll_fd);
|
||||
#else
|
||||
close (_epoll_fd);
|
||||
#endif
|
||||
for (retired_t::iterator it = _retired.begin (), end = _retired.end ();
|
||||
it != end; ++it) {
|
||||
LIBZMQ_DELETE (*it);
|
||||
}
|
||||
}
|
||||
|
||||
zmq::epoll_t::handle_t zmq::epoll_t::add_fd (fd_t fd_, i_poll_events *events_)
|
||||
{
|
||||
check_thread ();
|
||||
poll_entry_t *pe = new (std::nothrow) poll_entry_t;
|
||||
alloc_assert (pe);
|
||||
|
||||
// The memset is not actually needed. It's here to prevent debugging
|
||||
// tools to complain about using uninitialised memory.
|
||||
memset (pe, 0, sizeof (poll_entry_t));
|
||||
|
||||
pe->fd = fd_;
|
||||
pe->ev.events = 0;
|
||||
pe->ev.data.ptr = pe;
|
||||
pe->events = events_;
|
||||
|
||||
const int rc = epoll_ctl (_epoll_fd, EPOLL_CTL_ADD, fd_, &pe->ev);
|
||||
errno_assert (rc != -1);
|
||||
|
||||
// Increase the load metric of the thread.
|
||||
adjust_load (1);
|
||||
|
||||
return pe;
|
||||
}
|
||||
|
||||
void zmq::epoll_t::rm_fd (handle_t handle_)
|
||||
{
|
||||
check_thread ();
|
||||
poll_entry_t *pe = static_cast<poll_entry_t *> (handle_);
|
||||
const int rc = epoll_ctl (_epoll_fd, EPOLL_CTL_DEL, pe->fd, &pe->ev);
|
||||
errno_assert (rc != -1);
|
||||
pe->fd = retired_fd;
|
||||
_retired.push_back (pe);
|
||||
|
||||
// Decrease the load metric of the thread.
|
||||
adjust_load (-1);
|
||||
}
|
||||
|
||||
void zmq::epoll_t::set_pollin (handle_t handle_)
|
||||
{
|
||||
check_thread ();
|
||||
poll_entry_t *pe = static_cast<poll_entry_t *> (handle_);
|
||||
pe->ev.events |= EPOLLIN;
|
||||
const int rc = epoll_ctl (_epoll_fd, EPOLL_CTL_MOD, pe->fd, &pe->ev);
|
||||
errno_assert (rc != -1);
|
||||
}
|
||||
|
||||
void zmq::epoll_t::reset_pollin (handle_t handle_)
|
||||
{
|
||||
check_thread ();
|
||||
poll_entry_t *pe = static_cast<poll_entry_t *> (handle_);
|
||||
pe->ev.events &= ~(static_cast<short> (EPOLLIN));
|
||||
const int rc = epoll_ctl (_epoll_fd, EPOLL_CTL_MOD, pe->fd, &pe->ev);
|
||||
errno_assert (rc != -1);
|
||||
}
|
||||
|
||||
void zmq::epoll_t::set_pollout (handle_t handle_)
|
||||
{
|
||||
check_thread ();
|
||||
poll_entry_t *pe = static_cast<poll_entry_t *> (handle_);
|
||||
pe->ev.events |= EPOLLOUT;
|
||||
const int rc = epoll_ctl (_epoll_fd, EPOLL_CTL_MOD, pe->fd, &pe->ev);
|
||||
errno_assert (rc != -1);
|
||||
}
|
||||
|
||||
void zmq::epoll_t::reset_pollout (handle_t handle_)
|
||||
{
|
||||
check_thread ();
|
||||
poll_entry_t *pe = static_cast<poll_entry_t *> (handle_);
|
||||
pe->ev.events &= ~(static_cast<short> (EPOLLOUT));
|
||||
const int rc = epoll_ctl (_epoll_fd, EPOLL_CTL_MOD, pe->fd, &pe->ev);
|
||||
errno_assert (rc != -1);
|
||||
}
|
||||
|
||||
void zmq::epoll_t::stop ()
|
||||
{
|
||||
check_thread ();
|
||||
}
|
||||
|
||||
int zmq::epoll_t::max_fds ()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
void zmq::epoll_t::loop ()
|
||||
{
|
||||
epoll_event ev_buf[max_io_events];
|
||||
|
||||
while (true) {
|
||||
// Execute any due timers.
|
||||
const int timeout = static_cast<int> (execute_timers ());
|
||||
|
||||
if (get_load () == 0) {
|
||||
if (timeout == 0)
|
||||
break;
|
||||
|
||||
// TODO sleep for timeout
|
||||
continue;
|
||||
}
|
||||
|
||||
// Wait for events.
|
||||
const int n = epoll_wait (_epoll_fd, &ev_buf[0], max_io_events,
|
||||
timeout ? timeout : -1);
|
||||
if (n == -1) {
|
||||
errno_assert (errno == EINTR);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
const poll_entry_t *const pe =
|
||||
static_cast<const poll_entry_t *> (ev_buf[i].data.ptr);
|
||||
|
||||
if (pe->fd == retired_fd)
|
||||
continue;
|
||||
if (ev_buf[i].events & (EPOLLERR | EPOLLHUP))
|
||||
pe->events->in_event ();
|
||||
if (pe->fd == retired_fd)
|
||||
continue;
|
||||
if (ev_buf[i].events & EPOLLOUT)
|
||||
pe->events->out_event ();
|
||||
if (pe->fd == retired_fd)
|
||||
continue;
|
||||
if (ev_buf[i].events & EPOLLIN)
|
||||
pe->events->in_event ();
|
||||
}
|
||||
|
||||
// Destroy retired event sources.
|
||||
for (retired_t::iterator it = _retired.begin (), end = _retired.end ();
|
||||
it != end; ++it) {
|
||||
LIBZMQ_DELETE (*it);
|
||||
}
|
||||
_retired.clear ();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
114
3rd/libzmq/src/epoll.hpp
Normal file
114
3rd/libzmq/src/epoll.hpp
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ZMQ_EPOLL_HPP_INCLUDED__
|
||||
#define __ZMQ_EPOLL_HPP_INCLUDED__
|
||||
|
||||
// poller.hpp decides which polling mechanism to use.
|
||||
#include "poller.hpp"
|
||||
#if defined ZMQ_IOTHREAD_POLLER_USE_EPOLL
|
||||
|
||||
#include <vector>
|
||||
|
||||
#if defined ZMQ_HAVE_WINDOWS
|
||||
#include "../external/wepoll/wepoll.h"
|
||||
#else
|
||||
#include <sys/epoll.h>
|
||||
#endif
|
||||
|
||||
#include "ctx.hpp"
|
||||
#include "fd.hpp"
|
||||
#include "thread.hpp"
|
||||
#include "poller_base.hpp"
|
||||
#include "mutex.hpp"
|
||||
|
||||
namespace zmq
|
||||
{
|
||||
struct i_poll_events;
|
||||
|
||||
// This class implements socket polling mechanism using the Linux-specific
|
||||
// epoll mechanism.
|
||||
|
||||
class epoll_t ZMQ_FINAL : public worker_poller_base_t
|
||||
{
|
||||
public:
|
||||
typedef void *handle_t;
|
||||
|
||||
epoll_t (const thread_ctx_t &ctx_);
|
||||
~epoll_t () ZMQ_OVERRIDE;
|
||||
|
||||
// "poller" concept.
|
||||
handle_t add_fd (fd_t fd_, zmq::i_poll_events *events_);
|
||||
void rm_fd (handle_t handle_);
|
||||
void set_pollin (handle_t handle_);
|
||||
void reset_pollin (handle_t handle_);
|
||||
void set_pollout (handle_t handle_);
|
||||
void reset_pollout (handle_t handle_);
|
||||
void stop ();
|
||||
|
||||
static int max_fds ();
|
||||
|
||||
private:
|
||||
#if defined ZMQ_HAVE_WINDOWS
|
||||
typedef HANDLE epoll_fd_t;
|
||||
static const epoll_fd_t epoll_retired_fd;
|
||||
#else
|
||||
typedef fd_t epoll_fd_t;
|
||||
enum
|
||||
{
|
||||
epoll_retired_fd = retired_fd
|
||||
};
|
||||
#endif
|
||||
|
||||
// Main event loop.
|
||||
void loop ();
|
||||
|
||||
// Main epoll file descriptor
|
||||
epoll_fd_t _epoll_fd;
|
||||
|
||||
struct poll_entry_t
|
||||
{
|
||||
fd_t fd;
|
||||
epoll_event ev;
|
||||
zmq::i_poll_events *events;
|
||||
};
|
||||
|
||||
// List of retired event sources.
|
||||
typedef std::vector<poll_entry_t *> retired_t;
|
||||
retired_t _retired;
|
||||
|
||||
ZMQ_NON_COPYABLE_NOR_MOVABLE (epoll_t)
|
||||
};
|
||||
|
||||
typedef epoll_t poller_t;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
453
3rd/libzmq/src/err.cpp
Normal file
453
3rd/libzmq/src/err.cpp
Normal file
@@ -0,0 +1,453 @@
|
||||
/*
|
||||
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "err.hpp"
|
||||
#include "macros.hpp"
|
||||
|
||||
const char *zmq::errno_to_string (int errno_)
|
||||
{
|
||||
switch (errno_) {
|
||||
#if defined ZMQ_HAVE_WINDOWS
|
||||
case ENOTSUP:
|
||||
return "Not supported";
|
||||
case EPROTONOSUPPORT:
|
||||
return "Protocol not supported";
|
||||
case ENOBUFS:
|
||||
return "No buffer space available";
|
||||
case ENETDOWN:
|
||||
return "Network is down";
|
||||
case EADDRINUSE:
|
||||
return "Address in use";
|
||||
case EADDRNOTAVAIL:
|
||||
return "Address not available";
|
||||
case ECONNREFUSED:
|
||||
return "Connection refused";
|
||||
case EINPROGRESS:
|
||||
return "Operation in progress";
|
||||
#endif
|
||||
case EFSM:
|
||||
return "Operation cannot be accomplished in current state";
|
||||
case ENOCOMPATPROTO:
|
||||
return "The protocol is not compatible with the socket type";
|
||||
case ETERM:
|
||||
return "Context was terminated";
|
||||
case EMTHREAD:
|
||||
return "No thread available";
|
||||
case EHOSTUNREACH:
|
||||
return "Host unreachable";
|
||||
default:
|
||||
#if defined _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4996)
|
||||
#endif
|
||||
return strerror (errno_);
|
||||
#if defined _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void zmq::zmq_abort (const char *errmsg_)
|
||||
{
|
||||
#if defined ZMQ_HAVE_WINDOWS
|
||||
|
||||
// Raise STATUS_FATAL_APP_EXIT.
|
||||
ULONG_PTR extra_info[1];
|
||||
extra_info[0] = (ULONG_PTR) errmsg_;
|
||||
RaiseException (0x40000015, EXCEPTION_NONCONTINUABLE, 1, extra_info);
|
||||
#else
|
||||
LIBZMQ_UNUSED (errmsg_);
|
||||
print_backtrace ();
|
||||
abort ();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef ZMQ_HAVE_WINDOWS
|
||||
|
||||
const char *zmq::wsa_error ()
|
||||
{
|
||||
return wsa_error_no (WSAGetLastError (), NULL);
|
||||
}
|
||||
|
||||
const char *zmq::wsa_error_no (int no_, const char *wsae_wouldblock_string_)
|
||||
{
|
||||
// TODO: It seems that list of Windows socket errors is longer than this.
|
||||
// Investigate whether there's a way to convert it into the string
|
||||
// automatically (wsaError->HRESULT->string?).
|
||||
switch (no_) {
|
||||
case WSABASEERR:
|
||||
return "No Error";
|
||||
case WSAEINTR:
|
||||
return "Interrupted system call";
|
||||
case WSAEBADF:
|
||||
return "Bad file number";
|
||||
case WSAEACCES:
|
||||
return "Permission denied";
|
||||
case WSAEFAULT:
|
||||
return "Bad address";
|
||||
case WSAEINVAL:
|
||||
return "Invalid argument";
|
||||
case WSAEMFILE:
|
||||
return "Too many open files";
|
||||
case WSAEWOULDBLOCK:
|
||||
return wsae_wouldblock_string_;
|
||||
case WSAEINPROGRESS:
|
||||
return "Operation now in progress";
|
||||
case WSAEALREADY:
|
||||
return "Operation already in progress";
|
||||
case WSAENOTSOCK:
|
||||
return "Socket operation on non-socket";
|
||||
case WSAEDESTADDRREQ:
|
||||
return "Destination address required";
|
||||
case WSAEMSGSIZE:
|
||||
return "Message too long";
|
||||
case WSAEPROTOTYPE:
|
||||
return "Protocol wrong type for socket";
|
||||
case WSAENOPROTOOPT:
|
||||
return "Bas protocol option";
|
||||
case WSAEPROTONOSUPPORT:
|
||||
return "Protocol not supported";
|
||||
case WSAESOCKTNOSUPPORT:
|
||||
return "Socket type not supported";
|
||||
case WSAEOPNOTSUPP:
|
||||
return "Operation not supported on socket";
|
||||
case WSAEPFNOSUPPORT:
|
||||
return "Protocol family not supported";
|
||||
case WSAEAFNOSUPPORT:
|
||||
return "Address family not supported by protocol family";
|
||||
case WSAEADDRINUSE:
|
||||
return "Address already in use";
|
||||
case WSAEADDRNOTAVAIL:
|
||||
return "Can't assign requested address";
|
||||
case WSAENETDOWN:
|
||||
return "Network is down";
|
||||
case WSAENETUNREACH:
|
||||
return "Network is unreachable";
|
||||
case WSAENETRESET:
|
||||
return "Net dropped connection or reset";
|
||||
case WSAECONNABORTED:
|
||||
return "Software caused connection abort";
|
||||
case WSAECONNRESET:
|
||||
return "Connection reset by peer";
|
||||
case WSAENOBUFS:
|
||||
return "No buffer space available";
|
||||
case WSAEISCONN:
|
||||
return "Socket is already connected";
|
||||
case WSAENOTCONN:
|
||||
return "Socket is not connected";
|
||||
case WSAESHUTDOWN:
|
||||
return "Can't send after socket shutdown";
|
||||
case WSAETOOMANYREFS:
|
||||
return "Too many references can't splice";
|
||||
case WSAETIMEDOUT:
|
||||
return "Connection timed out";
|
||||
case WSAECONNREFUSED:
|
||||
return "Connection refused";
|
||||
case WSAELOOP:
|
||||
return "Too many levels of symbolic links";
|
||||
case WSAENAMETOOLONG:
|
||||
return "File name too long";
|
||||
case WSAEHOSTDOWN:
|
||||
return "Host is down";
|
||||
case WSAEHOSTUNREACH:
|
||||
return "No Route to Host";
|
||||
case WSAENOTEMPTY:
|
||||
return "Directory not empty";
|
||||
case WSAEPROCLIM:
|
||||
return "Too many processes";
|
||||
case WSAEUSERS:
|
||||
return "Too many users";
|
||||
case WSAEDQUOT:
|
||||
return "Disc Quota Exceeded";
|
||||
case WSAESTALE:
|
||||
return "Stale NFS file handle";
|
||||
case WSAEREMOTE:
|
||||
return "Too many levels of remote in path";
|
||||
case WSASYSNOTREADY:
|
||||
return "Network SubSystem is unavailable";
|
||||
case WSAVERNOTSUPPORTED:
|
||||
return "WINSOCK DLL Version out of range";
|
||||
case WSANOTINITIALISED:
|
||||
return "Successful WSASTARTUP not yet performed";
|
||||
case WSAHOST_NOT_FOUND:
|
||||
return "Host not found";
|
||||
case WSATRY_AGAIN:
|
||||
return "Non-Authoritative Host not found";
|
||||
case WSANO_RECOVERY:
|
||||
return "Non-Recoverable errors: FORMERR REFUSED NOTIMP";
|
||||
case WSANO_DATA:
|
||||
return "Valid name no data record of requested";
|
||||
default:
|
||||
return "error not defined";
|
||||
}
|
||||
}
|
||||
|
||||
void zmq::win_error (char *buffer_, size_t buffer_size_)
|
||||
{
|
||||
const DWORD errcode = GetLastError ();
|
||||
#if defined _WIN32_WCE
|
||||
DWORD rc = FormatMessageW (
|
||||
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errcode,
|
||||
MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR) buffer_,
|
||||
buffer_size_ / sizeof (wchar_t), NULL);
|
||||
#else
|
||||
const DWORD rc = FormatMessageA (
|
||||
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errcode,
|
||||
MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), buffer_,
|
||||
static_cast<DWORD> (buffer_size_), NULL);
|
||||
#endif
|
||||
zmq_assert (rc);
|
||||
}
|
||||
|
||||
int zmq::wsa_error_to_errno (int errcode_)
|
||||
{
|
||||
switch (errcode_) {
|
||||
// 10004 - Interrupted system call.
|
||||
case WSAEINTR:
|
||||
return EINTR;
|
||||
// 10009 - File handle is not valid.
|
||||
case WSAEBADF:
|
||||
return EBADF;
|
||||
// 10013 - Permission denied.
|
||||
case WSAEACCES:
|
||||
return EACCES;
|
||||
// 10014 - Bad address.
|
||||
case WSAEFAULT:
|
||||
return EFAULT;
|
||||
// 10022 - Invalid argument.
|
||||
case WSAEINVAL:
|
||||
return EINVAL;
|
||||
// 10024 - Too many open files.
|
||||
case WSAEMFILE:
|
||||
return EMFILE;
|
||||
// 10035 - Operation would block.
|
||||
case WSAEWOULDBLOCK:
|
||||
return EBUSY;
|
||||
// 10036 - Operation now in progress.
|
||||
case WSAEINPROGRESS:
|
||||
return EAGAIN;
|
||||
// 10037 - Operation already in progress.
|
||||
case WSAEALREADY:
|
||||
return EAGAIN;
|
||||
// 10038 - Socket operation on non-socket.
|
||||
case WSAENOTSOCK:
|
||||
return ENOTSOCK;
|
||||
// 10039 - Destination address required.
|
||||
case WSAEDESTADDRREQ:
|
||||
return EFAULT;
|
||||
// 10040 - Message too long.
|
||||
case WSAEMSGSIZE:
|
||||
return EMSGSIZE;
|
||||
// 10041 - Protocol wrong type for socket.
|
||||
case WSAEPROTOTYPE:
|
||||
return EFAULT;
|
||||
// 10042 - Bad protocol option.
|
||||
case WSAENOPROTOOPT:
|
||||
return EINVAL;
|
||||
// 10043 - Protocol not supported.
|
||||
case WSAEPROTONOSUPPORT:
|
||||
return EPROTONOSUPPORT;
|
||||
// 10044 - Socket type not supported.
|
||||
case WSAESOCKTNOSUPPORT:
|
||||
return EFAULT;
|
||||
// 10045 - Operation not supported on socket.
|
||||
case WSAEOPNOTSUPP:
|
||||
return EFAULT;
|
||||
// 10046 - Protocol family not supported.
|
||||
case WSAEPFNOSUPPORT:
|
||||
return EPROTONOSUPPORT;
|
||||
// 10047 - Address family not supported by protocol family.
|
||||
case WSAEAFNOSUPPORT:
|
||||
return EAFNOSUPPORT;
|
||||
// 10048 - Address already in use.
|
||||
case WSAEADDRINUSE:
|
||||
return EADDRINUSE;
|
||||
// 10049 - Cannot assign requested address.
|
||||
case WSAEADDRNOTAVAIL:
|
||||
return EADDRNOTAVAIL;
|
||||
// 10050 - Network is down.
|
||||
case WSAENETDOWN:
|
||||
return ENETDOWN;
|
||||
// 10051 - Network is unreachable.
|
||||
case WSAENETUNREACH:
|
||||
return ENETUNREACH;
|
||||
// 10052 - Network dropped connection on reset.
|
||||
case WSAENETRESET:
|
||||
return ENETRESET;
|
||||
// 10053 - Software caused connection abort.
|
||||
case WSAECONNABORTED:
|
||||
return ECONNABORTED;
|
||||
// 10054 - Connection reset by peer.
|
||||
case WSAECONNRESET:
|
||||
return ECONNRESET;
|
||||
// 10055 - No buffer space available.
|
||||
case WSAENOBUFS:
|
||||
return ENOBUFS;
|
||||
// 10056 - Socket is already connected.
|
||||
case WSAEISCONN:
|
||||
return EFAULT;
|
||||
// 10057 - Socket is not connected.
|
||||
case WSAENOTCONN:
|
||||
return ENOTCONN;
|
||||
// 10058 - Can't send after socket shutdown.
|
||||
case WSAESHUTDOWN:
|
||||
return EFAULT;
|
||||
// 10059 - Too many references can't splice.
|
||||
case WSAETOOMANYREFS:
|
||||
return EFAULT;
|
||||
// 10060 - Connection timed out.
|
||||
case WSAETIMEDOUT:
|
||||
return ETIMEDOUT;
|
||||
// 10061 - Connection refused.
|
||||
case WSAECONNREFUSED:
|
||||
return ECONNREFUSED;
|
||||
// 10062 - Too many levels of symbolic links.
|
||||
case WSAELOOP:
|
||||
return EFAULT;
|
||||
// 10063 - File name too long.
|
||||
case WSAENAMETOOLONG:
|
||||
return EFAULT;
|
||||
// 10064 - Host is down.
|
||||
case WSAEHOSTDOWN:
|
||||
return EAGAIN;
|
||||
// 10065 - No route to host.
|
||||
case WSAEHOSTUNREACH:
|
||||
return EHOSTUNREACH;
|
||||
// 10066 - Directory not empty.
|
||||
case WSAENOTEMPTY:
|
||||
return EFAULT;
|
||||
// 10067 - Too many processes.
|
||||
case WSAEPROCLIM:
|
||||
return EFAULT;
|
||||
// 10068 - Too many users.
|
||||
case WSAEUSERS:
|
||||
return EFAULT;
|
||||
// 10069 - Disc Quota Exceeded.
|
||||
case WSAEDQUOT:
|
||||
return EFAULT;
|
||||
// 10070 - Stale NFS file handle.
|
||||
case WSAESTALE:
|
||||
return EFAULT;
|
||||
// 10071 - Too many levels of remote in path.
|
||||
case WSAEREMOTE:
|
||||
return EFAULT;
|
||||
// 10091 - Network SubSystem is unavailable.
|
||||
case WSASYSNOTREADY:
|
||||
return EFAULT;
|
||||
// 10092 - WINSOCK DLL Version out of range.
|
||||
case WSAVERNOTSUPPORTED:
|
||||
return EFAULT;
|
||||
// 10093 - Successful WSASTARTUP not yet performed.
|
||||
case WSANOTINITIALISED:
|
||||
return EFAULT;
|
||||
// 11001 - Host not found.
|
||||
case WSAHOST_NOT_FOUND:
|
||||
return EFAULT;
|
||||
// 11002 - Non-Authoritative Host not found.
|
||||
case WSATRY_AGAIN:
|
||||
return EFAULT;
|
||||
// 11003 - Non-Recoverable errors: FORMERR REFUSED NOTIMP.
|
||||
case WSANO_RECOVERY:
|
||||
return EFAULT;
|
||||
// 11004 - Valid name no data record of requested.
|
||||
case WSANO_DATA:
|
||||
return EFAULT;
|
||||
default:
|
||||
wsa_assert (false);
|
||||
}
|
||||
// Not reachable
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_LIBUNWIND) && !defined(__SUNPRO_CC)
|
||||
|
||||
#define UNW_LOCAL_ONLY
|
||||
#include <libunwind.h>
|
||||
#include <dlfcn.h>
|
||||
#include <cxxabi.h>
|
||||
#include "mutex.hpp"
|
||||
|
||||
void zmq::print_backtrace (void)
|
||||
{
|
||||
static zmq::mutex_t mtx;
|
||||
mtx.lock ();
|
||||
Dl_info dl_info;
|
||||
unw_cursor_t cursor;
|
||||
unw_context_t ctx;
|
||||
unsigned frame_n = 0;
|
||||
|
||||
unw_getcontext (&ctx);
|
||||
unw_init_local (&cursor, &ctx);
|
||||
|
||||
while (unw_step (&cursor) > 0) {
|
||||
unw_word_t offset;
|
||||
unw_proc_info_t p_info;
|
||||
static const char unknown[] = "?";
|
||||
const char *file_name;
|
||||
char *demangled_name;
|
||||
char func_name[256] = "";
|
||||
void *addr;
|
||||
int rc;
|
||||
|
||||
if (unw_get_proc_info (&cursor, &p_info))
|
||||
break;
|
||||
|
||||
rc = unw_get_proc_name (&cursor, func_name, 256, &offset);
|
||||
if (rc == -UNW_ENOINFO)
|
||||
memcpy (func_name, unknown, sizeof unknown);
|
||||
|
||||
addr = (void *) (p_info.start_ip + offset);
|
||||
|
||||
if (dladdr (addr, &dl_info) && dl_info.dli_fname)
|
||||
file_name = dl_info.dli_fname;
|
||||
else
|
||||
file_name = unknown;
|
||||
|
||||
demangled_name = abi::__cxa_demangle (func_name, NULL, NULL, &rc);
|
||||
|
||||
printf ("#%u %p in %s (%s+0x%lx)\n", frame_n++, addr, file_name,
|
||||
rc ? func_name : demangled_name, (unsigned long) offset);
|
||||
free (demangled_name);
|
||||
}
|
||||
puts ("");
|
||||
|
||||
fflush (stdout);
|
||||
mtx.unlock ();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void zmq::print_backtrace ()
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
183
3rd/libzmq/src/err.hpp
Normal file
183
3rd/libzmq/src/err.hpp
Normal file
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ZMQ_ERR_HPP_INCLUDED__
|
||||
#define __ZMQ_ERR_HPP_INCLUDED__
|
||||
|
||||
#include <assert.h>
|
||||
#if defined _WIN32_WCE
|
||||
#include "..\builds\msvc\errno.hpp"
|
||||
#else
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef ZMQ_HAVE_WINDOWS
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
|
||||
#include "likely.hpp"
|
||||
|
||||
// 0MQ-specific error codes are defined in zmq.h
|
||||
|
||||
// EPROTO is not used by OpenBSD and maybe other platforms.
|
||||
#ifndef EPROTO
|
||||
#define EPROTO 0
|
||||
#endif
|
||||
|
||||
namespace zmq
|
||||
{
|
||||
const char *errno_to_string (int errno_);
|
||||
#if defined __clang__
|
||||
#if __has_feature(attribute_analyzer_noreturn)
|
||||
void zmq_abort (const char *errmsg_) __attribute__ ((analyzer_noreturn));
|
||||
#else
|
||||
void zmq_abort (const char *errmsg_);
|
||||
#endif
|
||||
#elif defined __MSCVER__
|
||||
__declspec(noreturn) void zmq_abort (const char *errmsg_);
|
||||
#else
|
||||
void zmq_abort (const char *errmsg_);
|
||||
#endif
|
||||
void print_backtrace ();
|
||||
}
|
||||
|
||||
#ifdef ZMQ_HAVE_WINDOWS
|
||||
|
||||
namespace zmq
|
||||
{
|
||||
const char *wsa_error ();
|
||||
const char *
|
||||
wsa_error_no (int no_,
|
||||
const char *wsae_wouldblock_string_ = "Operation would block");
|
||||
void win_error (char *buffer_, size_t buffer_size_);
|
||||
int wsa_error_to_errno (int errcode_);
|
||||
}
|
||||
|
||||
// Provides convenient way to check WSA-style errors on Windows.
|
||||
#define wsa_assert(x) \
|
||||
do { \
|
||||
if (unlikely (!(x))) { \
|
||||
const char *errstr = zmq::wsa_error (); \
|
||||
if (errstr != NULL) { \
|
||||
fprintf (stderr, "Assertion failed: %s [%i] (%s:%d)\n", \
|
||||
errstr, WSAGetLastError (), __FILE__, __LINE__); \
|
||||
fflush (stderr); \
|
||||
zmq::zmq_abort (errstr); \
|
||||
} \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
// Provides convenient way to assert on WSA-style errors on Windows.
|
||||
#define wsa_assert_no(no) \
|
||||
do { \
|
||||
const char *errstr = zmq::wsa_error_no (no); \
|
||||
if (errstr != NULL) { \
|
||||
fprintf (stderr, "Assertion failed: %s (%s:%d)\n", errstr, \
|
||||
__FILE__, __LINE__); \
|
||||
fflush (stderr); \
|
||||
zmq::zmq_abort (errstr); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
// Provides convenient way to check GetLastError-style errors on Windows.
|
||||
#define win_assert(x) \
|
||||
do { \
|
||||
if (unlikely (!(x))) { \
|
||||
char errstr[256]; \
|
||||
zmq::win_error (errstr, 256); \
|
||||
fprintf (stderr, "Assertion failed: %s (%s:%d)\n", errstr, \
|
||||
__FILE__, __LINE__); \
|
||||
fflush (stderr); \
|
||||
zmq::zmq_abort (errstr); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#endif
|
||||
|
||||
// This macro works in exactly the same way as the normal assert. It is used
|
||||
// in its stead because standard assert on Win32 in broken - it prints nothing
|
||||
// when used within the scope of JNI library.
|
||||
#define zmq_assert(x) \
|
||||
do { \
|
||||
if (unlikely (!(x))) { \
|
||||
fprintf (stderr, "Assertion failed: %s (%s:%d)\n", #x, __FILE__, \
|
||||
__LINE__); \
|
||||
fflush (stderr); \
|
||||
zmq::zmq_abort (#x); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
// Provides convenient way to check for errno-style errors.
|
||||
#define errno_assert(x) \
|
||||
do { \
|
||||
if (unlikely (!(x))) { \
|
||||
const char *errstr = strerror (errno); \
|
||||
fprintf (stderr, "%s (%s:%d)\n", errstr, __FILE__, __LINE__); \
|
||||
fflush (stderr); \
|
||||
zmq::zmq_abort (errstr); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
// Provides convenient way to check for POSIX errors.
|
||||
#define posix_assert(x) \
|
||||
do { \
|
||||
if (unlikely (x)) { \
|
||||
const char *errstr = strerror (x); \
|
||||
fprintf (stderr, "%s (%s:%d)\n", errstr, __FILE__, __LINE__); \
|
||||
fflush (stderr); \
|
||||
zmq::zmq_abort (errstr); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
// Provides convenient way to check for errors from getaddrinfo.
|
||||
#define gai_assert(x) \
|
||||
do { \
|
||||
if (unlikely (x)) { \
|
||||
const char *errstr = gai_strerror (x); \
|
||||
fprintf (stderr, "%s (%s:%d)\n", errstr, __FILE__, __LINE__); \
|
||||
fflush (stderr); \
|
||||
zmq::zmq_abort (errstr); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
// Provides convenient way to check whether memory allocation have succeeded.
|
||||
#define alloc_assert(x) \
|
||||
do { \
|
||||
if (unlikely (!x)) { \
|
||||
fprintf (stderr, "FATAL ERROR: OUT OF MEMORY (%s:%d)\n", __FILE__, \
|
||||
__LINE__); \
|
||||
fflush (stderr); \
|
||||
zmq::zmq_abort ("FATAL ERROR: OUT OF MEMORY"); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#endif
|
||||
63
3rd/libzmq/src/fd.hpp
Normal file
63
3rd/libzmq/src/fd.hpp
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ZMQ_FD_HPP_INCLUDED__
|
||||
#define __ZMQ_FD_HPP_INCLUDED__
|
||||
|
||||
#if defined _WIN32
|
||||
#include "windows.hpp"
|
||||
#endif
|
||||
|
||||
namespace zmq
|
||||
{
|
||||
typedef zmq_fd_t fd_t;
|
||||
|
||||
#ifdef ZMQ_HAVE_WINDOWS
|
||||
#if defined _MSC_VER && _MSC_VER <= 1400
|
||||
enum
|
||||
{
|
||||
retired_fd = (fd_t) (~0)
|
||||
};
|
||||
#else
|
||||
enum
|
||||
#if _MSC_VER >= 1800
|
||||
: fd_t
|
||||
#endif
|
||||
{
|
||||
retired_fd = INVALID_SOCKET
|
||||
};
|
||||
#endif
|
||||
#else
|
||||
enum
|
||||
{
|
||||
retired_fd = -1
|
||||
};
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
150
3rd/libzmq/src/fq.cpp
Normal file
150
3rd/libzmq/src/fq.cpp
Normal file
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "fq.hpp"
|
||||
#include "pipe.hpp"
|
||||
#include "err.hpp"
|
||||
#include "msg.hpp"
|
||||
|
||||
zmq::fq_t::fq_t () : _active (0), _last_in (NULL), _current (0), _more (false)
|
||||
{
|
||||
}
|
||||
|
||||
zmq::fq_t::~fq_t ()
|
||||
{
|
||||
zmq_assert (_pipes.empty ());
|
||||
}
|
||||
|
||||
void zmq::fq_t::attach (pipe_t *pipe_)
|
||||
{
|
||||
_pipes.push_back (pipe_);
|
||||
_pipes.swap (_active, _pipes.size () - 1);
|
||||
_active++;
|
||||
}
|
||||
|
||||
void zmq::fq_t::pipe_terminated (pipe_t *pipe_)
|
||||
{
|
||||
const pipes_t::size_type index = _pipes.index (pipe_);
|
||||
|
||||
// Remove the pipe from the list; adjust number of active pipes
|
||||
// accordingly.
|
||||
if (index < _active) {
|
||||
_active--;
|
||||
_pipes.swap (index, _active);
|
||||
if (_current == _active)
|
||||
_current = 0;
|
||||
}
|
||||
_pipes.erase (pipe_);
|
||||
|
||||
if (_last_in == pipe_) {
|
||||
_last_in = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void zmq::fq_t::activated (pipe_t *pipe_)
|
||||
{
|
||||
// Move the pipe to the list of active pipes.
|
||||
_pipes.swap (_pipes.index (pipe_), _active);
|
||||
_active++;
|
||||
}
|
||||
|
||||
int zmq::fq_t::recv (msg_t *msg_)
|
||||
{
|
||||
return recvpipe (msg_, NULL);
|
||||
}
|
||||
|
||||
int zmq::fq_t::recvpipe (msg_t *msg_, pipe_t **pipe_)
|
||||
{
|
||||
// Deallocate old content of the message.
|
||||
int rc = msg_->close ();
|
||||
errno_assert (rc == 0);
|
||||
|
||||
// Round-robin over the pipes to get the next message.
|
||||
while (_active > 0) {
|
||||
// Try to fetch new message. If we've already read part of the message
|
||||
// subsequent part should be immediately available.
|
||||
const bool fetched = _pipes[_current]->read (msg_);
|
||||
|
||||
// Note that when message is not fetched, current pipe is deactivated
|
||||
// and replaced by another active pipe. Thus we don't have to increase
|
||||
// the 'current' pointer.
|
||||
if (fetched) {
|
||||
if (pipe_)
|
||||
*pipe_ = _pipes[_current];
|
||||
_more = (msg_->flags () & msg_t::more) != 0;
|
||||
if (!_more) {
|
||||
_last_in = _pipes[_current];
|
||||
_current = (_current + 1) % _active;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Check the atomicity of the message.
|
||||
// If we've already received the first part of the message
|
||||
// we should get the remaining parts without blocking.
|
||||
zmq_assert (!_more);
|
||||
|
||||
_active--;
|
||||
_pipes.swap (_current, _active);
|
||||
if (_current == _active)
|
||||
_current = 0;
|
||||
}
|
||||
|
||||
// No message is available. Initialise the output parameter
|
||||
// to be a 0-byte message.
|
||||
rc = msg_->init ();
|
||||
errno_assert (rc == 0);
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool zmq::fq_t::has_in ()
|
||||
{
|
||||
// There are subsequent parts of the partly-read message available.
|
||||
if (_more)
|
||||
return true;
|
||||
|
||||
// Note that messing with current doesn't break the fairness of fair
|
||||
// queueing algorithm. If there are no messages available current will
|
||||
// get back to its original value. Otherwise it'll point to the first
|
||||
// pipe holding messages, skipping only pipes with no messages available.
|
||||
while (_active > 0) {
|
||||
if (_pipes[_current]->check_read ())
|
||||
return true;
|
||||
|
||||
// Deactivate the pipe.
|
||||
_active--;
|
||||
_pipes.swap (_current, _active);
|
||||
if (_current == _active)
|
||||
_current = 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
84
3rd/libzmq/src/fq.hpp
Normal file
84
3rd/libzmq/src/fq.hpp
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ZMQ_FQ_HPP_INCLUDED__
|
||||
#define __ZMQ_FQ_HPP_INCLUDED__
|
||||
|
||||
#include "array.hpp"
|
||||
#include "blob.hpp"
|
||||
|
||||
namespace zmq
|
||||
{
|
||||
class msg_t;
|
||||
class pipe_t;
|
||||
|
||||
// Class manages a set of inbound pipes. On receive it performs fair
|
||||
// queueing so that senders gone berserk won't cause denial of
|
||||
// service for decent senders.
|
||||
|
||||
class fq_t
|
||||
{
|
||||
public:
|
||||
fq_t ();
|
||||
~fq_t ();
|
||||
|
||||
void attach (pipe_t *pipe_);
|
||||
void activated (pipe_t *pipe_);
|
||||
void pipe_terminated (pipe_t *pipe_);
|
||||
|
||||
int recv (msg_t *msg_);
|
||||
int recvpipe (msg_t *msg_, pipe_t **pipe_);
|
||||
bool has_in ();
|
||||
|
||||
private:
|
||||
// Inbound pipes.
|
||||
typedef array_t<pipe_t, 1> pipes_t;
|
||||
pipes_t _pipes;
|
||||
|
||||
// Number of active pipes. All the active pipes are located at the
|
||||
// beginning of the pipes array.
|
||||
pipes_t::size_type _active;
|
||||
|
||||
// Pointer to the last pipe we received message from.
|
||||
// NULL when no message has been received or the pipe
|
||||
// has terminated.
|
||||
pipe_t *_last_in;
|
||||
|
||||
// Index of the next bound pipe to read a message from.
|
||||
pipes_t::size_type _current;
|
||||
|
||||
// If true, part of a multipart message was already received, but
|
||||
// there are following parts still waiting in the current pipe.
|
||||
bool _more;
|
||||
|
||||
ZMQ_NON_COPYABLE_NOR_MOVABLE (fq_t)
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
91
3rd/libzmq/src/gather.cpp
Normal file
91
3rd/libzmq/src/gather.cpp
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "macros.hpp"
|
||||
#include "gather.hpp"
|
||||
#include "err.hpp"
|
||||
#include "msg.hpp"
|
||||
#include "pipe.hpp"
|
||||
|
||||
zmq::gather_t::gather_t (class ctx_t *parent_, uint32_t tid_, int sid_) :
|
||||
socket_base_t (parent_, tid_, sid_, true)
|
||||
{
|
||||
options.type = ZMQ_GATHER;
|
||||
}
|
||||
|
||||
zmq::gather_t::~gather_t ()
|
||||
{
|
||||
}
|
||||
|
||||
void zmq::gather_t::xattach_pipe (pipe_t *pipe_,
|
||||
bool subscribe_to_all_,
|
||||
bool locally_initiated_)
|
||||
{
|
||||
LIBZMQ_UNUSED (subscribe_to_all_);
|
||||
LIBZMQ_UNUSED (locally_initiated_);
|
||||
|
||||
zmq_assert (pipe_);
|
||||
_fq.attach (pipe_);
|
||||
}
|
||||
|
||||
void zmq::gather_t::xread_activated (pipe_t *pipe_)
|
||||
{
|
||||
_fq.activated (pipe_);
|
||||
}
|
||||
|
||||
void zmq::gather_t::xpipe_terminated (pipe_t *pipe_)
|
||||
{
|
||||
_fq.pipe_terminated (pipe_);
|
||||
}
|
||||
|
||||
int zmq::gather_t::xrecv (msg_t *msg_)
|
||||
{
|
||||
int rc = _fq.recvpipe (msg_, NULL);
|
||||
|
||||
// Drop any messages with more flag
|
||||
while (rc == 0 && msg_->flags () & msg_t::more) {
|
||||
// drop all frames of the current multi-frame message
|
||||
rc = _fq.recvpipe (msg_, NULL);
|
||||
|
||||
while (rc == 0 && msg_->flags () & msg_t::more)
|
||||
rc = _fq.recvpipe (msg_, NULL);
|
||||
|
||||
// get the new message
|
||||
if (rc == 0)
|
||||
rc = _fq.recvpipe (msg_, NULL);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
bool zmq::gather_t::xhas_in ()
|
||||
{
|
||||
return _fq.has_in ();
|
||||
}
|
||||
66
3rd/libzmq/src/gather.hpp
Normal file
66
3rd/libzmq/src/gather.hpp
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ZMQ_GATHER_HPP_INCLUDED__
|
||||
#define __ZMQ_GATHER_HPP_INCLUDED__
|
||||
|
||||
#include "socket_base.hpp"
|
||||
#include "fq.hpp"
|
||||
|
||||
namespace zmq
|
||||
{
|
||||
class ctx_t;
|
||||
class pipe_t;
|
||||
class msg_t;
|
||||
|
||||
class gather_t ZMQ_FINAL : public socket_base_t
|
||||
{
|
||||
public:
|
||||
gather_t (zmq::ctx_t *parent_, uint32_t tid_, int sid_);
|
||||
~gather_t ();
|
||||
|
||||
protected:
|
||||
// Overrides of functions from socket_base_t.
|
||||
void xattach_pipe (zmq::pipe_t *pipe_,
|
||||
bool subscribe_to_all_,
|
||||
bool locally_initiated_);
|
||||
int xrecv (zmq::msg_t *msg_);
|
||||
bool xhas_in ();
|
||||
void xread_activated (zmq::pipe_t *pipe_);
|
||||
void xpipe_terminated (zmq::pipe_t *pipe_);
|
||||
|
||||
private:
|
||||
// Fair queueing object for inbound pipes.
|
||||
fq_t _fq;
|
||||
|
||||
ZMQ_NON_COPYABLE_NOR_MOVABLE (gather_t)
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
117
3rd/libzmq/src/generic_mtrie.hpp
Normal file
117
3rd/libzmq/src/generic_mtrie.hpp
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
Copyright (c) 2018 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ZMQ_GENERIC_MTRIE_HPP_INCLUDED__
|
||||
#define __ZMQ_GENERIC_MTRIE_HPP_INCLUDED__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <set>
|
||||
|
||||
#include "macros.hpp"
|
||||
#include "stdint.hpp"
|
||||
|
||||
namespace zmq
|
||||
{
|
||||
// Multi-trie (prefix tree). Each node in the trie is a set of pointers.
|
||||
template <typename T> class generic_mtrie_t
|
||||
{
|
||||
public:
|
||||
typedef T value_t;
|
||||
typedef const unsigned char *prefix_t;
|
||||
|
||||
enum rm_result
|
||||
{
|
||||
not_found,
|
||||
last_value_removed,
|
||||
values_remain
|
||||
};
|
||||
|
||||
generic_mtrie_t ();
|
||||
~generic_mtrie_t ();
|
||||
|
||||
// Add key to the trie. Returns true iff no entry with the same prefix_
|
||||
// and size_ existed before.
|
||||
bool add (prefix_t prefix_, size_t size_, value_t *value_);
|
||||
|
||||
// Remove all entries with a specific value from the trie.
|
||||
// The call_on_uniq_ flag controls if the callback is invoked
|
||||
// when there are no entries left on a prefix only (true)
|
||||
// or on every removal (false). The arg_ argument is passed
|
||||
// through to the callback function.
|
||||
template <typename Arg>
|
||||
void rm (value_t *value_,
|
||||
void (*func_) (const unsigned char *data_, size_t size_, Arg arg_),
|
||||
Arg arg_,
|
||||
bool call_on_uniq_);
|
||||
|
||||
// Removes a specific entry from the trie.
|
||||
// Returns the result of the operation.
|
||||
rm_result rm (prefix_t prefix_, size_t size_, value_t *value_);
|
||||
|
||||
// Calls a callback function for all matching entries, i.e. any node
|
||||
// corresponding to data_ or a prefix of it. The arg_ argument
|
||||
// is passed through to the callback function.
|
||||
template <typename Arg>
|
||||
void match (prefix_t data_,
|
||||
size_t size_,
|
||||
void (*func_) (value_t *value_, Arg arg_),
|
||||
Arg arg_);
|
||||
|
||||
private:
|
||||
bool is_redundant () const;
|
||||
|
||||
typedef std::set<value_t *> pipes_t;
|
||||
pipes_t *_pipes;
|
||||
|
||||
unsigned char _min;
|
||||
unsigned short _count;
|
||||
unsigned short _live_nodes;
|
||||
union _next_t
|
||||
{
|
||||
class generic_mtrie_t<value_t> *node;
|
||||
class generic_mtrie_t<value_t> **table;
|
||||
} _next;
|
||||
|
||||
struct iter
|
||||
{
|
||||
generic_mtrie_t<value_t> *node;
|
||||
generic_mtrie_t<value_t> *next_node;
|
||||
prefix_t prefix;
|
||||
size_t size;
|
||||
unsigned short current_child;
|
||||
unsigned char new_min;
|
||||
unsigned char new_max;
|
||||
bool processed_for_removal;
|
||||
};
|
||||
|
||||
ZMQ_NON_COPYABLE_NOR_MOVABLE (generic_mtrie_t)
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
593
3rd/libzmq/src/generic_mtrie_impl.hpp
Normal file
593
3rd/libzmq/src/generic_mtrie_impl.hpp
Normal file
@@ -0,0 +1,593 @@
|
||||
/*
|
||||
Copyright (c) 2018 Contributors as noted in the AUTHORS file
|
||||
|
||||
This file is part of libzmq, the ZeroMQ core engine in C++.
|
||||
|
||||
libzmq is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||
by the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
As a special exception, the Contributors give you permission to link
|
||||
this library with independent modules to produce an executable,
|
||||
regardless of the license terms of these independent modules, and to
|
||||
copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the
|
||||
terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library.
|
||||
If you modify this library, you must extend this exception to your
|
||||
version of the library.
|
||||
|
||||
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ZMQ_GENERIC_MTRIE_IMPL_HPP_INCLUDED__
|
||||
#define __ZMQ_GENERIC_MTRIE_IMPL_HPP_INCLUDED__
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <new>
|
||||
#include <algorithm>
|
||||
#include <list>
|
||||
|
||||
#include "err.hpp"
|
||||
#include "macros.hpp"
|
||||
#include "generic_mtrie.hpp"
|
||||
|
||||
namespace zmq
|
||||
{
|
||||
template <typename T>
|
||||
generic_mtrie_t<T>::generic_mtrie_t () :
|
||||
_pipes (0),
|
||||
_min (0),
|
||||
_count (0),
|
||||
_live_nodes (0)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename T> generic_mtrie_t<T>::~generic_mtrie_t ()
|
||||
{
|
||||
LIBZMQ_DELETE (_pipes);
|
||||
|
||||
if (_count == 1) {
|
||||
zmq_assert (_next.node);
|
||||
LIBZMQ_DELETE (_next.node);
|
||||
} else if (_count > 1) {
|
||||
for (unsigned short i = 0; i != _count; ++i) {
|
||||
LIBZMQ_DELETE (_next.table[i]);
|
||||
}
|
||||
free (_next.table);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool generic_mtrie_t<T>::add (prefix_t prefix_, size_t size_, value_t *pipe_)
|
||||
{
|
||||
generic_mtrie_t<value_t> *it = this;
|
||||
|
||||
while (size_) {
|
||||
const unsigned char c = *prefix_;
|
||||
|
||||
if (c < it->_min || c >= it->_min + it->_count) {
|
||||
// The character is out of range of currently handled
|
||||
// characters. We have to extend the table.
|
||||
if (!it->_count) {
|
||||
it->_min = c;
|
||||
it->_count = 1;
|
||||
it->_next.node = NULL;
|
||||
} else if (it->_count == 1) {
|
||||
const unsigned char oldc = it->_min;
|
||||
generic_mtrie_t *oldp = it->_next.node;
|
||||
it->_count = (it->_min < c ? c - it->_min : it->_min - c) + 1;
|
||||
it->_next.table = static_cast<generic_mtrie_t **> (
|
||||
malloc (sizeof (generic_mtrie_t *) * it->_count));
|
||||
alloc_assert (it->_next.table);
|
||||
for (unsigned short i = 0; i != it->_count; ++i)
|
||||
it->_next.table[i] = 0;
|
||||
it->_min = std::min (it->_min, c);
|
||||
it->_next.table[oldc - it->_min] = oldp;
|
||||
} else if (it->_min < c) {
|
||||
// The new character is above the current character range.
|
||||
const unsigned short old_count = it->_count;
|
||||
it->_count = c - it->_min + 1;
|
||||
it->_next.table = static_cast<generic_mtrie_t **> (realloc (
|
||||
it->_next.table, sizeof (generic_mtrie_t *) * it->_count));
|
||||
alloc_assert (it->_next.table);
|
||||
for (unsigned short i = old_count; i != it->_count; i++)
|
||||
it->_next.table[i] = NULL;
|
||||
} else {
|
||||
// The new character is below the current character range.
|
||||
const unsigned short old_count = it->_count;
|
||||
it->_count = (it->_min + old_count) - c;
|
||||
it->_next.table = static_cast<generic_mtrie_t **> (realloc (
|
||||
it->_next.table, sizeof (generic_mtrie_t *) * it->_count));
|
||||
alloc_assert (it->_next.table);
|
||||
memmove (it->_next.table + it->_min - c, it->_next.table,
|
||||
old_count * sizeof (generic_mtrie_t *));
|
||||
for (unsigned short i = 0; i != it->_min - c; i++)
|
||||
it->_next.table[i] = NULL;
|
||||
it->_min = c;
|
||||
}
|
||||
}
|
||||
|
||||
// If next node does not exist, create one.
|
||||
if (it->_count == 1) {
|
||||
if (!it->_next.node) {
|
||||
it->_next.node = new (std::nothrow) generic_mtrie_t;
|
||||
alloc_assert (it->_next.node);
|
||||
++(it->_live_nodes);
|
||||
}
|
||||
|
||||
++prefix_;
|
||||
--size_;
|
||||
it = it->_next.node;
|
||||
} else {
|
||||
if (!it->_next.table[c - it->_min]) {
|
||||
it->_next.table[c - it->_min] =
|
||||
new (std::nothrow) generic_mtrie_t;
|
||||
alloc_assert (it->_next.table[c - it->_min]);
|
||||
++(it->_live_nodes);
|
||||
}
|
||||
|
||||
++prefix_;
|
||||
--size_;
|
||||
it = it->_next.table[c - it->_min];
|
||||
}
|
||||
}
|
||||
|
||||
// We are at the node corresponding to the prefix. We are done.
|
||||
const bool result = !it->_pipes;
|
||||
if (!it->_pipes) {
|
||||
it->_pipes = new (std::nothrow) pipes_t;
|
||||
alloc_assert (it->_pipes);
|
||||
}
|
||||
it->_pipes->insert (pipe_);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
template <typename Arg>
|
||||
void generic_mtrie_t<T>::rm (value_t *pipe_,
|
||||
void (*func_) (prefix_t data_,
|
||||
size_t size_,
|
||||
Arg arg_),
|
||||
Arg arg_,
|
||||
bool call_on_uniq_)
|
||||
{
|
||||
// This used to be implemented as a non-tail recursive travesal of the trie,
|
||||
// which means remote clients controlled the depth of the recursion and the
|
||||
// stack size.
|
||||
// To simulate the non-tail recursion, with post-recursion changes depending on
|
||||
// the result of the recursive call, a stack is used to re-visit the same node
|
||||
// and operate on it again after children have been visisted.
|
||||
// A boolean is used to record whether the node had already been visited and to
|
||||
// determine if the pre- or post- children visit actions have to be taken.
|
||||
// In the case of a node with (N > 1) children, the node has to be re-visited
|
||||
// N times, in the correct order after each child visit.
|
||||
std::list<struct iter> stack;
|
||||
unsigned char *buff = NULL;
|
||||
size_t maxbuffsize = 0;
|
||||
struct iter it = {this, NULL, NULL, 0, 0, 0, 0, false};
|
||||
stack.push_back (it);
|
||||
|
||||
while (!stack.empty ()) {
|
||||
it = stack.back ();
|
||||
stack.pop_back ();
|
||||
|
||||
if (!it.processed_for_removal) {
|
||||
// Remove the subscription from this node.
|
||||
if (it.node->_pipes && it.node->_pipes->erase (pipe_)) {
|
||||
if (!call_on_uniq_ || it.node->_pipes->empty ()) {
|
||||
func_ (buff, it.size, arg_);
|
||||
}
|
||||
|
||||
if (it.node->_pipes->empty ()) {
|
||||
LIBZMQ_DELETE (it.node->_pipes);
|
||||
}
|
||||
}
|
||||
|
||||
// Adjust the buffer.
|
||||
if (it.size >= maxbuffsize) {
|
||||
maxbuffsize = it.size + 256;
|
||||
buff =
|
||||
static_cast<unsigned char *> (realloc (buff, maxbuffsize));
|
||||
alloc_assert (buff);
|
||||
}
|
||||
|
||||
switch (it.node->_count) {
|
||||
case 0:
|
||||
// If there are no subnodes in the trie, we are done with this node
|
||||
// pre-processing.
|
||||
break;
|
||||
case 1: {
|
||||
// If there's one subnode (optimisation).
|
||||
|
||||
buff[it.size] = it.node->_min;
|
||||
// Mark this node as pre-processed and push it, so that the next
|
||||
// visit after the operation on the child can do the removals.
|
||||
it.processed_for_removal = true;
|
||||
stack.push_back (it);
|
||||
struct iter next = {it.node->_next.node,
|
||||
NULL,
|
||||
NULL,
|
||||
++it.size,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
false};
|
||||
stack.push_back (next);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// If there are multiple subnodes.
|
||||
// When first visiting this node, initialize the new_min/max parameters
|
||||
// which will then be used after each child has been processed, on the
|
||||
// post-children iterations.
|
||||
if (it.current_child == 0) {
|
||||
// New min non-null character in the node table after the removal
|
||||
it.new_min = it.node->_min + it.node->_count - 1;
|
||||
// New max non-null character in the node table after the removal
|
||||
it.new_max = it.node->_min;
|
||||
}
|
||||
|
||||
// Mark this node as pre-processed and push it, so that the next
|
||||
// visit after the operation on the child can do the removals.
|
||||
buff[it.size] = it.node->_min + it.current_child;
|
||||
it.processed_for_removal = true;
|
||||
stack.push_back (it);
|
||||
if (it.node->_next.table[it.current_child]) {
|
||||
struct iter next = {
|
||||
it.node->_next.table[it.current_child],
|
||||
NULL,
|
||||
NULL,
|
||||
it.size + 1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
false};
|
||||
stack.push_back (next);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Reset back for the next time, in case this node doesn't get deleted.
|
||||
// This is done unconditionally, unlike when setting this variable to true.
|
||||
it.processed_for_removal = false;
|
||||
|
||||
switch (it.node->_count) {
|
||||
case 0:
|
||||
// If there are no subnodes in the trie, we are done with this node
|
||||
// post-processing.
|
||||
break;
|
||||
case 1:
|
||||
// If there's one subnode (optimisation).
|
||||
|
||||
// Prune the node if it was made redundant by the removal
|
||||
if (it.node->_next.node->is_redundant ()) {
|
||||
LIBZMQ_DELETE (it.node->_next.node);
|
||||
it.node->_count = 0;
|
||||
--it.node->_live_nodes;
|
||||
zmq_assert (it.node->_live_nodes == 0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// If there are multiple subnodes.
|
||||
{
|
||||
if (it.node->_next.table[it.current_child]) {
|
||||
// Prune redundant nodes from the mtrie
|
||||
if (it.node->_next.table[it.current_child]
|
||||
->is_redundant ()) {
|
||||
LIBZMQ_DELETE (
|
||||
it.node->_next.table[it.current_child]);
|
||||
|
||||
zmq_assert (it.node->_live_nodes > 0);
|
||||
--it.node->_live_nodes;
|
||||
} else {
|
||||
// The node is not redundant, so it's a candidate for being
|
||||
// the new min/max node.
|
||||
//
|
||||
// We loop through the node array from left to right, so the
|
||||
// first non-null, non-redundant node encountered is the new
|
||||
// minimum index. Conversely, the last non-redundant, non-null
|
||||
// node encountered is the new maximum index.
|
||||
if (it.current_child + it.node->_min
|
||||
< it.new_min)
|
||||
it.new_min =
|
||||
it.current_child + it.node->_min;
|
||||
if (it.current_child + it.node->_min
|
||||
> it.new_max)
|
||||
it.new_max =
|
||||
it.current_child + it.node->_min;
|
||||
}
|
||||
}
|
||||
|
||||
// If there are more children to visit, push again the current
|
||||
// node, so that pre-processing can happen on the next child.
|
||||
// If we are done, reset the child index so that the ::rm is
|
||||
// fully idempotent.
|
||||
++it.current_child;
|
||||
if (it.current_child >= it.node->_count)
|
||||
it.current_child = 0;
|
||||
else {
|
||||
stack.push_back (it);
|
||||
continue;
|
||||
}
|
||||
|
||||
// All children have been visited and removed if needed, and
|
||||
// all pre- and post-visit operations have been carried.
|
||||
// Resize/free the node table if needed.
|
||||
zmq_assert (it.node->_count > 1);
|
||||
|
||||
// Free the node table if it's no longer used.
|
||||
switch (it.node->_live_nodes) {
|
||||
case 0:
|
||||
free (it.node->_next.table);
|
||||
it.node->_next.table = NULL;
|
||||
it.node->_count = 0;
|
||||
break;
|
||||
case 1:
|
||||
// Compact the node table if possible
|
||||
|
||||
// If there's only one live node in the table we can
|
||||
// switch to using the more compact single-node
|
||||
// representation
|
||||
zmq_assert (it.new_min == it.new_max);
|
||||
zmq_assert (it.new_min >= it.node->_min);
|
||||
zmq_assert (it.new_min
|
||||
< it.node->_min + it.node->_count);
|
||||
{
|
||||
generic_mtrie_t *node =
|
||||
it.node->_next
|
||||
.table[it.new_min - it.node->_min];
|
||||
zmq_assert (node);
|
||||
free (it.node->_next.table);
|
||||
it.node->_next.node = node;
|
||||
}
|
||||
it.node->_count = 1;
|
||||
it.node->_min = it.new_min;
|
||||
break;
|
||||
default:
|
||||
if (it.new_min > it.node->_min
|
||||
|| it.new_max < it.node->_min
|
||||
+ it.node->_count - 1) {
|
||||
zmq_assert (it.new_max - it.new_min + 1
|
||||
> 1);
|
||||
|
||||
generic_mtrie_t **old_table =
|
||||
it.node->_next.table;
|
||||
zmq_assert (it.new_min > it.node->_min
|
||||
|| it.new_max
|
||||
< it.node->_min
|
||||
+ it.node->_count - 1);
|
||||
zmq_assert (it.new_min >= it.node->_min);
|
||||
zmq_assert (it.new_max
|
||||
<= it.node->_min
|
||||
+ it.node->_count - 1);
|
||||
zmq_assert (it.new_max - it.new_min + 1
|
||||
< it.node->_count);
|
||||
|
||||
it.node->_count =
|
||||
it.new_max - it.new_min + 1;
|
||||
it.node->_next.table =
|
||||
static_cast<generic_mtrie_t **> (
|
||||
malloc (sizeof (generic_mtrie_t *)
|
||||
* it.node->_count));
|
||||
alloc_assert (it.node->_next.table);
|
||||
|
||||
memmove (it.node->_next.table,
|
||||
old_table
|
||||
+ (it.new_min - it.node->_min),
|
||||
sizeof (generic_mtrie_t *)
|
||||
* it.node->_count);
|
||||
free (old_table);
|
||||
|
||||
it.node->_min = it.new_min;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free (buff);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename generic_mtrie_t<T>::rm_result
|
||||
generic_mtrie_t<T>::rm (prefix_t prefix_, size_t size_, value_t *pipe_)
|
||||
{
|
||||
// This used to be implemented as a non-tail recursive travesal of the trie,
|
||||
// which means remote clients controlled the depth of the recursion and the
|
||||
// stack size.
|
||||
// To simulate the non-tail recursion, with post-recursion changes depending on
|
||||
// the result of the recursive call, a stack is used to re-visit the same node
|
||||
// and operate on it again after children have been visisted.
|
||||
// A boolean is used to record whether the node had already been visited and to
|
||||
// determine if the pre- or post- children visit actions have to be taken.
|
||||
rm_result ret = not_found;
|
||||
std::list<struct iter> stack;
|
||||
struct iter it = {this, NULL, prefix_, size_, 0, 0, 0, false};
|
||||
stack.push_back (it);
|
||||
|
||||
while (!stack.empty ()) {
|
||||
it = stack.back ();
|
||||
stack.pop_back ();
|
||||
|
||||
if (!it.processed_for_removal) {
|
||||
if (!it.size) {
|
||||
if (!it.node->_pipes) {
|
||||
ret = not_found;
|
||||
continue;
|
||||
}
|
||||
|
||||
typename pipes_t::size_type erased =
|
||||
it.node->_pipes->erase (pipe_);
|
||||
if (it.node->_pipes->empty ()) {
|
||||
zmq_assert (erased == 1);
|
||||
LIBZMQ_DELETE (it.node->_pipes);
|
||||
ret = last_value_removed;
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = (erased == 1) ? values_remain : not_found;
|
||||
continue;
|
||||
}
|
||||
|
||||
it.current_child = *it.prefix;
|
||||
if (!it.node->_count || it.current_child < it.node->_min
|
||||
|| it.current_child >= it.node->_min + it.node->_count) {
|
||||
ret = not_found;
|
||||
continue;
|
||||
}
|
||||
|
||||
it.next_node =
|
||||
it.node->_count == 1
|
||||
? it.node->_next.node
|
||||
: it.node->_next.table[it.current_child - it.node->_min];
|
||||
if (!it.next_node) {
|
||||
ret = not_found;
|
||||
continue;
|
||||
}
|
||||
|
||||
it.processed_for_removal = true;
|
||||
stack.push_back (it);
|
||||
struct iter next = {
|
||||
it.next_node, NULL, it.prefix + 1, it.size - 1, 0, 0, 0, false};
|
||||
stack.push_back (next);
|
||||
} else {
|
||||
it.processed_for_removal = false;
|
||||
|
||||
if (it.next_node->is_redundant ()) {
|
||||
LIBZMQ_DELETE (it.next_node);
|
||||
zmq_assert (it.node->_count > 0);
|
||||
|
||||
if (it.node->_count == 1) {
|
||||
it.node->_next.node = NULL;
|
||||
it.node->_count = 0;
|
||||
--it.node->_live_nodes;
|
||||
zmq_assert (it.node->_live_nodes == 0);
|
||||
} else {
|
||||
it.node->_next.table[it.current_child - it.node->_min] = 0;
|
||||
zmq_assert (it.node->_live_nodes > 1);
|
||||
--it.node->_live_nodes;
|
||||
|
||||
// Compact the table if possible
|
||||
if (it.node->_live_nodes == 1) {
|
||||
// If there's only one live node in the table we can
|
||||
// switch to using the more compact single-node
|
||||
// representation
|
||||
unsigned short i;
|
||||
for (i = 0; i < it.node->_count; ++i)
|
||||
if (it.node->_next.table[i])
|
||||
break;
|
||||
|
||||
zmq_assert (i < it.node->_count);
|
||||
it.node->_min += i;
|
||||
it.node->_count = 1;
|
||||
generic_mtrie_t *oldp = it.node->_next.table[i];
|
||||
free (it.node->_next.table);
|
||||
it.node->_next.table = NULL;
|
||||
it.node->_next.node = oldp;
|
||||
} else if (it.current_child == it.node->_min) {
|
||||
// We can compact the table "from the left"
|
||||
unsigned short i;
|
||||
for (i = 1; i < it.node->_count; ++i)
|
||||
if (it.node->_next.table[i])
|
||||
break;
|
||||
|
||||
zmq_assert (i < it.node->_count);
|
||||
it.node->_min += i;
|
||||
it.node->_count -= i;
|
||||
generic_mtrie_t **old_table = it.node->_next.table;
|
||||
it.node->_next.table =
|
||||
static_cast<generic_mtrie_t **> (malloc (
|
||||
sizeof (generic_mtrie_t *) * it.node->_count));
|
||||
alloc_assert (it.node->_next.table);
|
||||
memmove (it.node->_next.table, old_table + i,
|
||||
sizeof (generic_mtrie_t *) * it.node->_count);
|
||||
free (old_table);
|
||||
} else if (it.current_child
|
||||
== it.node->_min + it.node->_count - 1) {
|
||||
// We can compact the table "from the right"
|
||||
unsigned short i;
|
||||
for (i = 1; i < it.node->_count; ++i)
|
||||
if (it.node->_next.table[it.node->_count - 1 - i])
|
||||
break;
|
||||
|
||||
zmq_assert (i < it.node->_count);
|
||||
it.node->_count -= i;
|
||||
generic_mtrie_t **old_table = it.node->_next.table;
|
||||
it.node->_next.table =
|
||||
static_cast<generic_mtrie_t **> (malloc (
|
||||
sizeof (generic_mtrie_t *) * it.node->_count));
|
||||
alloc_assert (it.node->_next.table);
|
||||
memmove (it.node->_next.table, old_table,
|
||||
sizeof (generic_mtrie_t *) * it.node->_count);
|
||||
free (old_table);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
template <typename Arg>
|
||||
void generic_mtrie_t<T>::match (prefix_t data_,
|
||||
size_t size_,
|
||||
void (*func_) (value_t *pipe_, Arg arg_),
|
||||
Arg arg_)
|
||||
{
|
||||
for (generic_mtrie_t *current = this; current; data_++, size_--) {
|
||||
// Signal the pipes attached to this node.
|
||||
if (current->_pipes) {
|
||||
for (typename pipes_t::iterator it = current->_pipes->begin (),
|
||||
end = current->_pipes->end ();
|
||||
it != end; ++it) {
|
||||
func_ (*it, arg_);
|
||||
}
|
||||
}
|
||||
|
||||
// If we are at the end of the message, there's nothing more to match.
|
||||
if (!size_)
|
||||
break;
|
||||
|
||||
// If there are no subnodes in the trie, return.
|
||||
if (current->_count == 0)
|
||||
break;
|
||||
|
||||
if (current->_count == 1) {
|
||||
// If there's one subnode (optimisation).
|
||||
if (data_[0] != current->_min) {
|
||||
break;
|
||||
}
|
||||
current = current->_next.node;
|
||||
} else {
|
||||
// If there are multiple subnodes.
|
||||
if (data_[0] < current->_min
|
||||
|| data_[0] >= current->_min + current->_count) {
|
||||
break;
|
||||
}
|
||||
current = current->_next.table[data_[0] - current->_min];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T> bool generic_mtrie_t<T>::is_redundant () const
|
||||
{
|
||||
return !_pipes && _live_nodes == 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user