Add clang format rules and checks (#935)

I would like to get feedback on this and see if people is confortable
with these clang rules.

Right now is using the "llvm" style increasing the line length from 80
to 120 given that coturn is using long lines often.

Co-authored-by: Pavel Punsky <eakraly@users.noreply.github.com>
This commit is contained in:
Gustavo Garcia 2022-11-06 21:05:17 +00:00 committed by GitHub
parent da2ae173c4
commit d9108a4b54
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
85 changed files with 35450 additions and 36364 deletions

29
.github/workflows/lint.yml vendored Normal file
View File

@ -0,0 +1,29 @@
name: Lint
on:
push:
branches: [ $default-branch ]
pull_request:
types: [ opened, reopened, synchronize ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
libevent-dev \
libssl-dev \
libpq-dev libmariadb-dev libsqlite3-dev \
libhiredis-dev \
libmongoc-dev \
libmicrohttpd-dev \
clang-format
- uses: actions/checkout@v3
- name: configure
run: ./configure
- name: lint
run: clang-format --version && make lint

View File

@ -45,6 +45,12 @@ test: check
check: bin/turnutils_rfc5769check
bin/turnutils_rfc5769check
format:
find . -iname "*.c" -o -iname "*.h" | xargs clang-format -i
lint:
find . -iname "*.c" -o -iname "*.h" | xargs clang-format --dry-run -Werror
include/turn/ns_turn_defs.h: src/ns_turn_defs.h
${RMCMD} include
${MKBUILDDIR} include/turn/client

View File

@ -1,9 +1,9 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ns_turn_utils.h"
#include "apputils.h"
#include "ns_turn_utils.h"
#include "stun_buffer.h"
static SHATYPE shatype = SHATYPE_SHA1;
@ -11,18 +11,20 @@ static SHATYPE shatype = SHATYPE_SHA1;
#define kMinInputLength 10
#define kMaxInputLength 5120
extern int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {//rfc5769check
extern int LLVMFuzzerTestOneInput(const uint8_t *Data,
size_t Size) { // rfc5769check
if (Size < kMinInputLength || Size > kMaxInputLength){
return 1;
}
if (Size < kMinInputLength || Size > kMaxInputLength) {
return 1;
}
stun_is_command_message_full_check_str((uint8_t *)Data, Size, 1, NULL);
stun_is_command_message_full_check_str((uint8_t *)Data, Size, 1, NULL);
uint8_t uname[33];
uint8_t realm[33];
uint8_t upwd[33];
strcpy((char*) upwd, "VOkJxbRl1RmTxUk/WvJxBt");
stun_check_message_integrity_str(TURN_CREDENTIALS_SHORT_TERM,(uint8_t *)Data, Size, uname, realm, upwd, shatype);
return 0;
uint8_t uname[33];
uint8_t realm[33];
uint8_t upwd[33];
strcpy((char *)upwd, "VOkJxbRl1RmTxUk/WvJxBt");
stun_check_message_integrity_str(TURN_CREDENTIALS_SHORT_TERM, (uint8_t *)Data,
Size, uname, realm, upwd, shatype);
return 0;
}

View File

@ -1,34 +1,35 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ns_turn_utils.h"
#include "apputils.h"
#include "ns_turn_utils.h"
#include "stun_buffer.h"
#define kMinInputLength 10
#define kMaxInputLength 5120
extern int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {//stunclient.c
if (Size < kMinInputLength || Size > kMaxInputLength){
return 1;
}
stun_buffer buf;
buf.len = Size;
memcpy(buf.buf,Data,buf.len);
if(stun_is_command_message(&buf)){
if(stun_is_response(&buf)){
if(stun_is_success_response(&buf)){
if(stun_is_binding_response(&buf)){
return 0;
}
}
}
}
extern int LLVMFuzzerTestOneInput(const uint8_t *Data,
size_t Size) { // stunclient.c
if (Size < kMinInputLength || Size > kMaxInputLength) {
return 1;
}
stun_buffer buf;
buf.len = Size;
memcpy(buf.buf, Data, buf.len);
if (stun_is_command_message(&buf)) {
if (stun_is_response(&buf)) {
if (stun_is_success_response(&buf)) {
if (stun_is_binding_response(&buf)) {
return 0;
}
}
}
}
return 1;
}

137
src/.clang-format Normal file
View File

@ -0,0 +1,137 @@
---
Language: Cpp
# BasedOnStyle: LLVM
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignConsecutiveMacros: false
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Right
AlignOperands: true
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: true
AllowAllConstructorInitializersOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortLambdasOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: MultiLine
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 120
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DeriveLineEnding: true
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
SortPriority: 0
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
Priority: 3
SortPriority: 0
- Regex: '.*'
Priority: 1
SortPriority: 0
IncludeIsMainRegex: '(Test)?$'
IncludeIsMainSourceRegex: ''
IndentCaseLabels: false
IndentGotoLabels: true
IndentPPDirectives: None
IndentWidth: 2
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
ReflowComments: true
SortIncludes: true
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInConditionalStatement: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
SpaceBeforeSquareBrackets: false
Standard: Latest
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
TabWidth: 8
UseCRLF: false
UseTab: Never
...

File diff suppressed because it is too large Load Diff

View File

@ -36,8 +36,8 @@
#include "ns_turn_openssl.h"
#include "ns_turn_ioaddr.h"
#include "ns_turn_msg_defs.h"
#include "ns_turn_ioalib.h"
#include "ns_turn_msg_defs.h"
#ifdef __cplusplus
extern "C" {
@ -68,48 +68,48 @@ extern int IS_TURN_SERVER;
#if defined(TURN_NO_TLS)
#define TLS_SUPPORTED 0
#define TLSv1_1_SUPPORTED 0
#define TLSv1_2_SUPPORTED 0
#define TLS_SUPPORTED 0
#define TLSv1_1_SUPPORTED 0
#define TLSv1_2_SUPPORTED 0
#else
#define TLS_SUPPORTED 1
#define TLS_SUPPORTED 1
#if defined(SSL_OP_NO_TLSv1_1)
#define TLSv1_1_SUPPORTED 1
#else
#define TLSv1_1_SUPPORTED 0
#endif
#if defined(SSL_OP_NO_TLSv1_1)
#define TLSv1_1_SUPPORTED 1
#else
#define TLSv1_1_SUPPORTED 0
#endif
#if defined(SSL_OP_NO_TLSv1_2)
#define TLSv1_2_SUPPORTED 1
#else
#define TLSv1_2_SUPPORTED 0
#endif
#if defined(SSL_OP_NO_TLSv1_3)
#define TLSv1_3_SUPPORTED 1
#else
#define TLSv1_3_SUPPORTED 0
#endif
#if defined(SSL_OP_NO_TLSv1_2)
#define TLSv1_2_SUPPORTED 1
#else
#define TLSv1_2_SUPPORTED 0
#endif
#if defined(SSL_OP_NO_TLSv1_3)
#define TLSv1_3_SUPPORTED 1
#else
#define TLSv1_3_SUPPORTED 0
#endif
#endif
#if defined(TURN_NO_DTLS) || (!defined(DTLS_CTRL_LISTEN) && (OPENSSL_VERSION_NUMBER < 0x10100000L))
#define DTLS_SUPPORTED 0
#define DTLSv1_2_SUPPORTED 0
#define DTLS_SUPPORTED 0
#define DTLSv1_2_SUPPORTED 0
#else
#define DTLS_SUPPORTED 1
#define DTLS_SUPPORTED 1
#if defined(SSL_OP_NO_DTLSv1_2)
#define DTLSv1_2_SUPPORTED 1
#else
#define DTLSv1_2_SUPPORTED 0
#endif
#define DTLSv1_2_SUPPORTED 1
#else
#define DTLSv1_2_SUPPORTED 0
#endif
#endif
@ -122,16 +122,16 @@ extern int IS_TURN_SERVER;
/////////// SSL //////////////////////////
enum _TURN_TLS_TYPE {
TURN_TLS_NO=0,
TURN_TLS_SSL23,
TURN_TLS_v1_0,
TURN_TLS_NO = 0,
TURN_TLS_SSL23,
TURN_TLS_v1_0,
#if TLSv1_1_SUPPORTED
TURN_TLS_v1_1,
TURN_TLS_v1_1,
#if TLSv1_2_SUPPORTED
TURN_TLS_v1_2,
TURN_TLS_v1_2,
#endif
#endif
TURN_TLS_TOTAL
TURN_TLS_TOTAL
};
typedef enum _TURN_TLS_TYPE TURN_TLS_TYPE;
@ -139,19 +139,24 @@ typedef enum _TURN_TLS_TYPE TURN_TLS_TYPE;
////////////////////////////////////////////
struct _oauth_key_data_raw {
char kid[OAUTH_KID_SIZE+1];
char ikm_key[OAUTH_KEY_SIZE+1];
uint64_t timestamp;
uint32_t lifetime;
char as_rs_alg[OAUTH_ALG_SIZE+1];
char realm[STUN_MAX_REALM_SIZE+1];
char kid[OAUTH_KID_SIZE + 1];
char ikm_key[OAUTH_KEY_SIZE + 1];
uint64_t timestamp;
uint32_t lifetime;
char as_rs_alg[OAUTH_ALG_SIZE + 1];
char realm[STUN_MAX_REALM_SIZE + 1];
};
typedef struct _oauth_key_data_raw oauth_key_data_raw;
//////////////////////////////////////////
#define EVENT_DEL(ev) if(ev) { event_del(ev); event_free(ev); ev=NULL; }
#define EVENT_DEL(ev) \
if (ev) { \
event_del(ev); \
event_free(ev); \
ev = NULL; \
}
//////////////////////////////////////////
@ -175,20 +180,28 @@ int set_sock_buf_size(evutil_socket_t fd, int sz);
int socket_init(void);
int socket_set_reusable(evutil_socket_t fd, int reusable, SOCKET_TYPE st);
int sock_bind_to_device(evutil_socket_t fd, const unsigned char* ifname);
int sock_bind_to_device(evutil_socket_t fd, const unsigned char *ifname);
int socket_set_nonblocking(evutil_socket_t fd);
int socket_tcp_set_keepalive(evutil_socket_t fd, SOCKET_TYPE st);
int addr_connect(evutil_socket_t fd, const ioa_addr* addr, int *out_errno);
int addr_connect(evutil_socket_t fd, const ioa_addr *addr, int *out_errno);
int addr_bind(evutil_socket_t fd, const ioa_addr* addr, int reusable, int debug, SOCKET_TYPE st);
int addr_bind(evutil_socket_t fd, const ioa_addr *addr, int reusable, int debug, SOCKET_TYPE st);
int addr_get_from_sock(evutil_socket_t fd, ioa_addr *addr);
int handle_socket_error(void);
#define CORRECT_RAW_TTL(ttl) do { if(ttl<0 || ttl>255) ttl=TTL_DEFAULT; } while(0)
#define CORRECT_RAW_TOS(tos) do { if(tos<0 || tos>255) tos=TOS_DEFAULT; } while(0)
#define CORRECT_RAW_TTL(ttl) \
do { \
if (ttl < 0 || ttl > 255) \
ttl = TTL_DEFAULT; \
} while (0)
#define CORRECT_RAW_TOS(tos) \
do { \
if (tos < 0 || tos > 255) \
tos = TOS_DEFAULT; \
} while (0)
int set_raw_socket_tos(evutil_socket_t fd, int family, int tos);
int set_raw_socket_ttl(evutil_socket_t fd, int family, int ttl);
@ -210,51 +223,47 @@ unsigned long get_system_number_of_cpus(void);
#define MTU_STEP (68)
int set_socket_df(evutil_socket_t fd, int family, int value);
int set_mtu_df(SSL* ssl, evutil_socket_t fd, int family, int mtu, int df_value, int verbose);
int decrease_mtu(SSL* ssl, int mtu, int verbose);
int set_mtu_df(SSL *ssl, evutil_socket_t fd, int family, int mtu, int df_value, int verbose);
int decrease_mtu(SSL *ssl, int mtu, int verbose);
int get_socket_mtu(evutil_socket_t fd, int family, int verbose);
////////////////// Misc utils /////////////////////////
char *skip_blanks(char* s);
char *skip_blanks(char *s);
#if defined(_MSC_VER)
#define CLOCK_REALTIME 0
int clock_gettime(int X, struct timeval* tv);
int gettimeofday(struct timeval* tp, void* tzp);
#define CLOCK_REALTIME 0
int clock_gettime(int X, struct timeval *tv);
int gettimeofday(struct timeval *tp, void *tzp);
char* dirname(char* path);
char *dirname(char *path);
#endif
#if defined(WINDOWS)
int getdomainname(char* name, size_t len);
// wchar convert to char
char* _WTA(__in wchar_t* pszInBufBuf, __in int nInSize, __out char** pszOutBuf, __out int* pnOutSize);
// char convert to wchar
wchar_t* _ATW(__in char* pszInBuf, __in int nInSize, __out wchar_t** pszOutBuf, __out int* pnOutSize);
int getdomainname(char *name, size_t len);
// wchar convert to char
char *_WTA(__in wchar_t *pszInBufBuf, __in int nInSize, __out char **pszOutBuf, __out int *pnOutSize);
// char convert to wchar
wchar_t *_ATW(__in char *pszInBuf, __in int nInSize, __out wchar_t **pszOutBuf, __out int *pnOutSize);
#endif
////////////////// File search ////////////////////////
char* find_config_file(const char *config_file, int print_file_name);
char *find_config_file(const char *config_file, int print_file_name);
void set_execdir(void);
void print_abs_file_name(const char *msg1, const char *msg2, const char *fn);
////////////////// Base64 /////////////////////////////
char *base64_encode(const unsigned char *data,
size_t input_length,
size_t *output_length);
char *base64_encode(const unsigned char *data, size_t input_length, size_t *output_length);
void build_base64_decoding_table(void);
unsigned char *base64_decode(const char *data,
size_t input_length,
size_t *output_length);
unsigned char *base64_decode(const char *data, size_t input_length, size_t *output_length);
///////////// SSL ////////////////
const char* turn_get_ssl_method(SSL *ssl, const char* mdefault);
const char *turn_get_ssl_method(SSL *ssl, const char *mdefault);
////////////// OAUTH UTILS ////////////////

View File

@ -33,34 +33,32 @@
#include "hiredis_libevent2.h"
#include "ns_turn_utils.h"
#include <event2/bufferevent.h>
#include <event2/buffer.h>
#include <event2/bufferevent.h>
#include <hiredis/hiredis.h>
#include <hiredis/async.h>
#include <hiredis/hiredis.h>
//////////////// Libevent context ///////////////////////
struct redisLibeventEvents
{
redisAsyncContext *context;
int invalid;
int allocated;
struct event_base *base;
struct event *rev, *wev;
int rev_set, wev_set;
char *ip;
int port;
char *pwd;
int db;
struct redisLibeventEvents {
redisAsyncContext *context;
int invalid;
int allocated;
struct event_base *base;
struct event *rev, *wev;
int rev_set, wev_set;
char *ip;
int port;
char *pwd;
int db;
};
///////////// Messages ////////////////////////////
struct redis_message
{
char format[513];
char arg[513];
struct redis_message {
char format[513];
char arg[513];
};
/////////////////// forward declarations ///////////////
@ -69,180 +67,175 @@ static void redis_reconnect(struct redisLibeventEvents *e);
//////////////////////////////////////////////////////////
static int redis_le_valid(struct redisLibeventEvents *e)
{
return (e && !(e->invalid) && (e->context));
}
static int redis_le_valid(struct redisLibeventEvents *e) { return (e && !(e->invalid) && (e->context)); }
/////////////////// Callbacks ////////////////////////////
static void redisLibeventReadEvent(int fd, short event, void *arg) {
((void)fd); ((void)event);
struct redisLibeventEvents *e = (struct redisLibeventEvents*)arg;
if(redis_le_valid(e)) {
{
char buf[8];
int len = 0;
do {
len = recv(fd,buf,sizeof(buf),MSG_PEEK);
} while((len<0)&&(errno == EINTR));
if(len<1) {
e->invalid = 1;
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: Redis connection broken: e=0x%lx\n", __FUNCTION__, ((unsigned long)e));
}
}
if(redis_le_valid(e)) {
redisAsyncHandleRead(e->context);
}
((void)fd);
((void)event);
struct redisLibeventEvents *e = (struct redisLibeventEvents *)arg;
if (redis_le_valid(e)) {
{
char buf[8];
int len = 0;
do {
len = recv(fd, buf, sizeof(buf), MSG_PEEK);
} while ((len < 0) && (errno == EINTR));
if (len < 1) {
e->invalid = 1;
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: Redis connection broken: e=0x%lx\n", __FUNCTION__, ((unsigned long)e));
}
}
if (redis_le_valid(e)) {
redisAsyncHandleRead(e->context);
}
} else {
redis_reconnect(e);
redis_reconnect(e);
}
}
static void redisLibeventWriteEvent(int fd, short event, void *arg) {
((void)fd); ((void)event);
struct redisLibeventEvents *e = (struct redisLibeventEvents*)arg;
if(redis_le_valid(e)) {
((void)fd);
((void)event);
struct redisLibeventEvents *e = (struct redisLibeventEvents *)arg;
if (redis_le_valid(e)) {
redisAsyncHandleWrite(e->context);
}
}
static void redisLibeventAddRead(void *privdata) {
struct redisLibeventEvents *e = (struct redisLibeventEvents*)privdata;
if(e && (e->rev) && !(e->rev_set)) {
event_add(e->rev,NULL);
struct redisLibeventEvents *e = (struct redisLibeventEvents *)privdata;
if (e && (e->rev) && !(e->rev_set)) {
event_add(e->rev, NULL);
e->rev_set = 1;
}
}
static void redisLibeventDelRead(void *privdata) {
struct redisLibeventEvents *e = (struct redisLibeventEvents*)privdata;
if(e && e->rev && e->rev_set) {
event_del(e->rev);
e->rev_set = 0;
}
struct redisLibeventEvents *e = (struct redisLibeventEvents *)privdata;
if (e && e->rev && e->rev_set) {
event_del(e->rev);
e->rev_set = 0;
}
}
static void redisLibeventAddWrite(void *privdata) {
struct redisLibeventEvents *e = (struct redisLibeventEvents*)privdata;
if(e && (e->wev) && !(e->wev_set)) {
event_add(e->wev,NULL);
e->wev_set = 1;
}
struct redisLibeventEvents *e = (struct redisLibeventEvents *)privdata;
if (e && (e->wev) && !(e->wev_set)) {
event_add(e->wev, NULL);
e->wev_set = 1;
}
}
static void redisLibeventDelWrite(void *privdata) {
struct redisLibeventEvents *e = (struct redisLibeventEvents*)privdata;
if(e && e->wev && e->wev_set) {
struct redisLibeventEvents *e = (struct redisLibeventEvents *)privdata;
if (e && e->wev && e->wev_set) {
event_del(e->wev);
e->wev_set = 0;
}
}
static void redisLibeventCleanup(void *privdata)
{
static void redisLibeventCleanup(void *privdata) {
if (privdata) {
if (privdata) {
struct redisLibeventEvents *e = (struct redisLibeventEvents *) privdata;
if (e->allocated) {
if (e->rev) {
if(e->rev_set)
event_del(e->rev);
event_free(e->rev);
e->rev = NULL;
}
e->rev_set = 0;
if (e->wev) {
if(e->wev_set)
event_del(e->wev);
event_free(e->wev);
e->wev = NULL;
}
e->wev_set = 0;
e->context = NULL;
}
}
struct redisLibeventEvents *e = (struct redisLibeventEvents *)privdata;
if (e->allocated) {
if (e->rev) {
if (e->rev_set)
event_del(e->rev);
event_free(e->rev);
e->rev = NULL;
}
e->rev_set = 0;
if (e->wev) {
if (e->wev_set)
event_del(e->wev);
event_free(e->wev);
e->wev = NULL;
}
e->wev_set = 0;
e->context = NULL;
}
}
}
///////////////////////// Send-receive ///////////////////////////
int is_redis_asyncconn_good(redis_context_handle rch)
{
if(rch) {
struct redisLibeventEvents *e = (struct redisLibeventEvents*)rch;
if(redis_le_valid(e))
return 1;
}
return 0;
int is_redis_asyncconn_good(redis_context_handle rch) {
if (rch) {
struct redisLibeventEvents *e = (struct redisLibeventEvents *)rch;
if (redis_le_valid(e))
return 1;
}
return 0;
}
void send_message_to_redis(redis_context_handle rch, const char *command, const char *key, const char *format,...)
{
if(!rch) {
return;
} else {
void send_message_to_redis(redis_context_handle rch, const char *command, const char *key, const char *format, ...) {
if (!rch) {
return;
} else {
struct redisLibeventEvents *e = (struct redisLibeventEvents*)rch;
struct redisLibeventEvents *e = (struct redisLibeventEvents *)rch;
if(!redis_le_valid(e)) {
redis_reconnect(e);
}
if (!redis_le_valid(e)) {
redis_reconnect(e);
}
if(!redis_le_valid(e)) {
;
} else {
if (!redis_le_valid(e)) {
;
} else {
redisAsyncContext *ac=e->context;
redisAsyncContext *ac = e->context;
struct redis_message rm;
struct redis_message rm;
snprintf(rm.format,sizeof(rm.format)-3,"%s %s ", command, key);
strcpy(rm.format+strlen(rm.format),"%s");
snprintf(rm.format, sizeof(rm.format) - 3, "%s %s ", command, key);
strcpy(rm.format + strlen(rm.format), "%s");
va_list args;
va_start (args, format);
vsnprintf(rm.arg, sizeof(rm.arg)-1, format, args);
va_end (args);
va_list args;
va_start(args, format);
vsnprintf(rm.arg, sizeof(rm.arg) - 1, format, args);
va_end(args);
if((redisAsyncCommand(ac, NULL, e, rm.format, rm.arg)!=REDIS_OK)) {
e->invalid = 1;
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: Redis connection broken: ac=0x%lx, e=0x%lx\n", __FUNCTION__,(unsigned long)ac,(unsigned long)e);
}
}
}
if ((redisAsyncCommand(ac, NULL, e, rm.format, rm.arg) != REDIS_OK)) {
e->invalid = 1;
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: Redis connection broken: ac=0x%lx, e=0x%lx\n", __FUNCTION__,
(unsigned long)ac, (unsigned long)e);
}
}
}
}
///////////////////////// Attach /////////////////////////////////
redis_context_handle redisLibeventAttach(struct event_base *base, char *ip0, int port0, char *pwd, int db)
{
redis_context_handle redisLibeventAttach(struct event_base *base, char *ip0, int port0, char *pwd, int db) {
struct redisLibeventEvents *e = NULL;
redisAsyncContext *ac = NULL;
char ip[256];
if(ip0 && ip0[0])
STRCPY(ip,ip0);
if (ip0 && ip0[0])
STRCPY(ip, ip0);
else
strncpy(ip,"127.0.0.1",sizeof(ip));
strncpy(ip, "127.0.0.1", sizeof(ip));
int port = DEFAULT_REDIS_PORT;
if(port0>0)
port=port0;
if (port0 > 0)
port = port0;
ac = redisAsyncConnect(ip, port);
if (!ac) {
fprintf(stderr,"Error: redisAsyncConnect returned NULL\n");
return NULL;
}
else if (ac->err) {
fprintf(stderr,"Error: %s:%s\n", ac->errstr, ac->c.errstr);
return NULL;
fprintf(stderr, "Error: redisAsyncConnect returned NULL\n");
return NULL;
} else if (ac->err) {
fprintf(stderr, "Error: %s:%s\n", ac->errstr, ac->c.errstr);
return NULL;
}
/* Create container for context and r/w events */
e = (struct redisLibeventEvents*)malloc(sizeof(struct redisLibeventEvents));
e = (struct redisLibeventEvents *)malloc(sizeof(struct redisLibeventEvents));
memset(e, 0, sizeof(struct redisLibeventEvents));
e->allocated = 1;
@ -250,8 +243,8 @@ redis_context_handle redisLibeventAttach(struct event_base *base, char *ip0, int
e->base = base;
e->ip = strdup(ip);
e->port = port;
if(pwd)
e->pwd = strdup(pwd);
if (pwd)
e->pwd = strdup(pwd);
e->db = db;
/* Register functions to start/stop listening for events */
@ -264,74 +257,69 @@ redis_context_handle redisLibeventAttach(struct event_base *base, char *ip0, int
ac->ev.data = e;
/* Initialize and install read/write events */
e->rev = event_new(e->base,e->context->c.fd,
EV_READ|EV_PERSIST,redisLibeventReadEvent,
e);
e->rev = event_new(e->base, e->context->c.fd, EV_READ | EV_PERSIST, redisLibeventReadEvent, e);
e->wev = event_new(e->base,e->context->c.fd,
EV_WRITE,redisLibeventWriteEvent,
e);
e->wev = event_new(e->base, e->context->c.fd, EV_WRITE, redisLibeventWriteEvent, e);
if (e->rev == NULL || e->wev == NULL) {
free(e);
return NULL;
free(e);
return NULL;
}
event_add(e->wev, NULL);
e->wev_set = 1;
//Authentication
if(redis_le_valid(e) && pwd) {
if(redisAsyncCommand(ac, NULL, e, "AUTH %s", pwd)!=REDIS_OK) {
e->invalid = 1;
}
// Authentication
if (redis_le_valid(e) && pwd) {
if (redisAsyncCommand(ac, NULL, e, "AUTH %s", pwd) != REDIS_OK) {
e->invalid = 1;
}
}
if(redis_le_valid(e)) {
if(redisAsyncCommand(ac, NULL, e, "SELECT %d", db)!=REDIS_OK) {
e->invalid = 1;
}
if (redis_le_valid(e)) {
if (redisAsyncCommand(ac, NULL, e, "SELECT %d", db) != REDIS_OK) {
e->invalid = 1;
}
}
return (redis_context_handle)e;
}
static void redis_reconnect(struct redisLibeventEvents *e)
{
if(!e || !(e->allocated))
return;
static void redis_reconnect(struct redisLibeventEvents *e) {
if (!e || !(e->allocated))
return;
if (e->rev) {
if(e->rev_set)
event_del(e->rev);
event_free(e->rev);
e->rev = NULL;
if (e->rev_set)
event_del(e->rev);
event_free(e->rev);
e->rev = NULL;
}
e->rev_set = 0;
if (e->wev) {
if(e->wev_set)
event_del(e->wev);
event_free(e->wev);
e->wev = NULL;
if (e->wev_set)
event_del(e->wev);
event_free(e->wev);
e->wev = NULL;
}
e->wev_set = 0;
redisAsyncContext *ac = NULL;
if(e->context) {
redisAsyncFree(e->context);
e->context = NULL;
if (e->context) {
redisAsyncFree(e->context);
e->context = NULL;
}
ac = redisAsyncConnect(e->ip, e->port);
if(!ac) {
return;
if (!ac) {
return;
}
e->context = ac;
/* Register functions to start/stop listening for events */
/* Register functions to start/stop listening for events */
ac->ev.addRead = redisLibeventAddRead;
ac->ev.delRead = redisLibeventDelRead;
ac->ev.addWrite = redisLibeventAddWrite;
@ -341,37 +329,33 @@ static void redis_reconnect(struct redisLibeventEvents *e)
ac->ev.data = e;
/* Initialize and install read/write events */
e->rev = event_new(e->base,e->context->c.fd,
EV_READ,redisLibeventReadEvent,
e);
e->rev = event_new(e->base, e->context->c.fd, EV_READ, redisLibeventReadEvent, e);
e->wev = event_new(e->base,e->context->c.fd,
EV_WRITE,redisLibeventWriteEvent,
e);
e->wev = event_new(e->base, e->context->c.fd, EV_WRITE, redisLibeventWriteEvent, e);
if (e->rev == NULL || e->wev == NULL) {
return;
return;
}
event_add(e->wev, NULL);
e->wev_set = 1;
e->invalid = 0;
//Authentication
if(redis_le_valid(e) && e->pwd) {
if(redisAsyncCommand(ac, NULL, e, "AUTH %s", e->pwd)!=REDIS_OK) {
e->invalid = 1;
}
// Authentication
if (redis_le_valid(e) && e->pwd) {
if (redisAsyncCommand(ac, NULL, e, "AUTH %s", e->pwd) != REDIS_OK) {
e->invalid = 1;
}
}
if(redis_le_valid(e)) {
if(redisAsyncCommand(ac, NULL, e, "SELECT %d", e->db)!=REDIS_OK) {
e->invalid = 1;
}
if (redis_le_valid(e)) {
if (redisAsyncCommand(ac, NULL, e, "SELECT %d", e->db) != REDIS_OK) {
e->invalid = 1;
}
}
if(redis_le_valid(e)) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: Re-connected to redis, async\n", __FUNCTION__);
if (redis_le_valid(e)) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: Re-connected to redis, async\n", __FUNCTION__);
}
}
@ -379,4 +363,3 @@ static void redis_reconnect(struct redisLibeventEvents *e)
#endif
/* TURN_NO_HIREDIS */

View File

@ -42,16 +42,15 @@ extern "C" {
#define DEFAULT_REDIS_PORT (6379)
typedef void* redis_context_handle;
typedef void *redis_context_handle;
//////////////////////////////////////
#if !defined(TURN_NO_HIREDIS)
redis_context_handle redisLibeventAttach(struct event_base *base, char *ip, int port, char *pwd, int db);
void send_message_to_redis(redis_context_handle rch, const char *command, const char *key, const char *format,...);
void send_message_to_redis(redis_context_handle rch, const char *command, const char *key, const char *format, ...);
int is_redis_asyncconn_good(redis_context_handle rch);

View File

@ -31,15 +31,15 @@
#ifndef __NST_OPENSSL_LIB__
#define __NST_OPENSSL_LIB__
#include <openssl/md5.h>
#include <openssl/hmac.h>
#include <openssl/ssl.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include <openssl/crypto.h>
#include <openssl/opensslv.h>
#include <openssl/dh.h>
#include <openssl/bn.h>
#include <openssl/crypto.h>
#include <openssl/dh.h>
#include <openssl/err.h>
#include <openssl/hmac.h>
#include <openssl/md5.h>
#include <openssl/opensslv.h>
#include <openssl/rand.h>
#include <openssl/ssl.h>
#endif //__NST_OPENSSL_LIB__

File diff suppressed because it is too large Load Diff

View File

@ -36,9 +36,9 @@
#endif
#if defined(WINDOWS)
#ifndef err
void err(int eval, const char *format, ...);
#endif
#ifndef err
void err(int eval, const char *format, ...);
#endif
#endif
#include "ns_turn_ioaddr.h"
@ -50,8 +50,8 @@ extern "C" {
//////////////////////// LOG //////////////////////////
typedef enum {
TURN_LOG_LEVEL_DEBUG = 0,
TURN_LOG_LEVEL_INFO,
TURN_LOG_LEVEL_DEBUG = 0,
TURN_LOG_LEVEL_INFO,
TURN_LOG_LEVEL_CONTROL,
TURN_LOG_LEVEL_WARNING,
TURN_LOG_LEVEL_ERROR
@ -61,7 +61,7 @@ typedef enum {
#define TURN_VERBOSE_NORMAL (1)
#define TURN_VERBOSE_EXTRA (2)
#define eve(v) ((v)==TURN_VERBOSE_EXTRA)
#define eve(v) ((v) == TURN_VERBOSE_EXTRA)
void set_no_stdout_log(int val);
void set_log_to_syslog(int val);
@ -69,15 +69,15 @@ void set_simple_log(int val);
void set_syslog_facility(char *val);
void set_turn_log_timestamp_format(char* new_format);
void set_turn_log_timestamp_format(char *new_format);
void turn_log_func_default(char* file, int line, TURN_LOG_LEVEL level, const char* format, ...)
void turn_log_func_default(char *file, int line, TURN_LOG_LEVEL level, const char *format, ...)
#ifdef __GNUC__
__attribute__ ((format (printf, 4, 5)))
__attribute__((format(printf, 4, 5)))
#endif
;
;
void addr_debug_print(int verbose, const ioa_addr *addr, const char* s);
void addr_debug_print(int verbose, const ioa_addr *addr, const char *s);
/* Log */
extern volatile int _log_time_value_set;

View File

@ -33,220 +33,208 @@
////////////////////// BUFFERS ///////////////////////////
int stun_init_buffer(stun_buffer *buf) {
if(!buf) return -1;
if (!buf)
return -1;
memset(buf->buf, 0, sizeof(buf->buf));
buf->len=0;
buf->offset=0;
buf->coffset=0;
buf->len = 0;
buf->offset = 0;
buf->coffset = 0;
return 0;
}
int stun_get_size(const stun_buffer *buf) {
if(!buf) return 0;
if (!buf)
return 0;
return sizeof(buf->buf);
}
////////////////////////////////////////////////////////////
void stun_tid_from_message(const stun_buffer *buf, stun_tid* id) {
stun_tid_from_message_str(buf->buf,(size_t)(buf->len), id);
void stun_tid_from_message(const stun_buffer *buf, stun_tid *id) {
stun_tid_from_message_str(buf->buf, (size_t)(buf->len), id);
}
void stun_tid_generate_in_message(stun_buffer* buf, stun_tid* id) {
if(buf) {
void stun_tid_generate_in_message(stun_buffer *buf, stun_tid *id) {
if (buf) {
stun_tid_generate_in_message_str(buf->buf, id);
}
}
////////////////////////////////////////////////////////
static inline int is_channel_msg(const stun_buffer* buf) {
if(buf && buf->len>0) {
static inline int is_channel_msg(const stun_buffer *buf) {
if (buf && buf->len > 0) {
return is_channel_msg_str(buf->buf, (size_t)(buf->len));
}
return 0;
}
int stun_is_command_message(const stun_buffer* buf) {
if(!buf || buf->len<=0)
int stun_is_command_message(const stun_buffer *buf) {
if (!buf || buf->len <= 0)
return 0;
else
return stun_is_command_message_str(buf->buf,(size_t)(buf->len));
return stun_is_command_message_str(buf->buf, (size_t)(buf->len));
}
int stun_is_request(const stun_buffer* buf) {
return stun_is_request_str(buf->buf,(size_t)buf->len);
}
int stun_is_request(const stun_buffer *buf) { return stun_is_request_str(buf->buf, (size_t)buf->len); }
int stun_is_success_response(const stun_buffer* buf) {
int stun_is_success_response(const stun_buffer *buf) {
return stun_is_success_response_str(buf->buf, (size_t)(buf->len));
}
int stun_is_error_response(const stun_buffer* buf, int *err_code, uint8_t *err_msg, size_t err_msg_size) {
int stun_is_error_response(const stun_buffer *buf, int *err_code, uint8_t *err_msg, size_t err_msg_size) {
return stun_is_error_response_str(buf->buf, (size_t)(buf->len), err_code, err_msg, err_msg_size);
}
int stun_is_response(const stun_buffer* buf) {
return stun_is_response_str(buf->buf,(size_t)(buf->len));
}
int stun_is_response(const stun_buffer *buf) { return stun_is_response_str(buf->buf, (size_t)(buf->len)); }
int stun_is_indication(const stun_buffer* buf) {
if(is_channel_msg(buf)) return 0;
int stun_is_indication(const stun_buffer *buf) {
if (is_channel_msg(buf))
return 0;
return IS_STUN_INDICATION(stun_get_msg_type(buf));
}
uint16_t stun_get_method(const stun_buffer* buf) {
return stun_get_method_str(buf->buf, (size_t)(buf->len));
}
uint16_t stun_get_method(const stun_buffer *buf) { return stun_get_method_str(buf->buf, (size_t)(buf->len)); }
uint16_t stun_get_msg_type(const stun_buffer* buf) {
if(!buf) return (uint16_t)-1;
return stun_get_msg_type_str(buf->buf,(size_t)buf->len);
uint16_t stun_get_msg_type(const stun_buffer *buf) {
if (!buf)
return (uint16_t)-1;
return stun_get_msg_type_str(buf->buf, (size_t)buf->len);
}
////////////////////////////////////////////////////////////
static void stun_init_command(uint16_t message_type, stun_buffer* buf) {
buf->len=stun_get_size(buf);
stun_init_command_str(message_type, buf->buf, (size_t*)(&(buf->len)));
static void stun_init_command(uint16_t message_type, stun_buffer *buf) {
buf->len = stun_get_size(buf);
stun_init_command_str(message_type, buf->buf, (size_t *)(&(buf->len)));
}
void stun_init_request(uint16_t method, stun_buffer* buf) {
stun_init_command(stun_make_request(method), buf);
void stun_init_request(uint16_t method, stun_buffer *buf) { stun_init_command(stun_make_request(method), buf); }
void stun_init_indication(uint16_t method, stun_buffer *buf) { stun_init_command(stun_make_indication(method), buf); }
void stun_init_success_response(uint16_t method, stun_buffer *buf, stun_tid *id) {
buf->len = stun_get_size(buf);
stun_init_success_response_str(method, buf->buf, (size_t *)(&(buf->len)), id);
}
void stun_init_indication(uint16_t method, stun_buffer* buf) {
stun_init_command(stun_make_indication(method), buf);
void stun_init_error_response(uint16_t method, stun_buffer *buf, uint16_t error_code, const uint8_t *reason,
stun_tid *id) {
buf->len = stun_get_size(buf);
stun_init_error_response_str(method, buf->buf, (size_t *)(&(buf->len)), error_code, reason, id);
}
void stun_init_success_response(uint16_t method, stun_buffer* buf, stun_tid* id) {
buf->len=stun_get_size(buf);
stun_init_success_response_str(method, buf->buf, (size_t*)(&(buf->len)), id);
}
void stun_init_error_response(uint16_t method, stun_buffer* buf, uint16_t error_code, const uint8_t *reason, stun_tid* id) {
buf->len=stun_get_size(buf);
stun_init_error_response_str(method, buf->buf, (size_t*)(&(buf->len)), error_code, reason, id);
}
///////////////////////////////////////////////////////////////////////////////
int stun_get_command_message_len(const stun_buffer* buf) {
int stun_get_command_message_len(const stun_buffer *buf) {
return stun_get_command_message_len_str(buf->buf, (size_t)(buf->len));
}
///////////////////////////////////////////////////////////////////////////////
int stun_init_channel_message(uint16_t chnumber, stun_buffer* buf, int length, int do_padding) {
return stun_init_channel_message_str(chnumber, buf->buf, (size_t*)(&(buf->len)), length, do_padding);
int stun_init_channel_message(uint16_t chnumber, stun_buffer *buf, int length, int do_padding) {
return stun_init_channel_message_str(chnumber, buf->buf, (size_t *)(&(buf->len)), length, do_padding);
}
int stun_is_channel_message(stun_buffer* buf, uint16_t* chnumber, int is_padding_mandatory) {
if(!buf) return 0;
int stun_is_channel_message(stun_buffer *buf, uint16_t *chnumber, int is_padding_mandatory) {
if (!buf)
return 0;
size_t blen = (size_t)buf->len;
int ret = stun_is_channel_message_str(buf->buf, &blen, chnumber, is_padding_mandatory);
if(ret) {
buf->len = blen;
if (ret) {
buf->len = blen;
}
return ret;
}
///////////////////////////////////////////////////////////////////////////////
int stun_set_allocate_request(stun_buffer* buf, uint32_t lifetime, int af4, int af6, uint8_t transport, int mobile, const char *rt, int ep) {
return stun_set_allocate_request_str(buf->buf, (size_t*)(&(buf->len)), lifetime, af4, af6, transport, mobile, rt, ep);
int stun_set_allocate_request(stun_buffer *buf, uint32_t lifetime, int af4, int af6, uint8_t transport, int mobile,
const char *rt, int ep) {
return stun_set_allocate_request_str(buf->buf, (size_t *)(&(buf->len)), lifetime, af4, af6, transport, mobile, rt,
ep);
}
int stun_set_allocate_response(stun_buffer* buf, stun_tid* tid,
const ioa_addr *relayed_addr1, const ioa_addr *relayed_addr2,
const ioa_addr *reflexive_addr,
uint32_t lifetime, uint32_t max_lifetime, int error_code, const uint8_t *reason,
uint64_t reservation_token, char *mobile_id) {
return stun_set_allocate_response_str(buf->buf, (size_t*)(&(buf->len)), tid,
relayed_addr1, relayed_addr2, reflexive_addr,
lifetime, max_lifetime, error_code, reason,
reservation_token, mobile_id);
int stun_set_allocate_response(stun_buffer *buf, stun_tid *tid, const ioa_addr *relayed_addr1,
const ioa_addr *relayed_addr2, const ioa_addr *reflexive_addr, uint32_t lifetime,
uint32_t max_lifetime, int error_code, const uint8_t *reason, uint64_t reservation_token,
char *mobile_id) {
return stun_set_allocate_response_str(buf->buf, (size_t *)(&(buf->len)), tid, relayed_addr1, relayed_addr2,
reflexive_addr, lifetime, max_lifetime, error_code, reason, reservation_token,
mobile_id);
}
///////////////////////////////////////////////////////////////////////////////
uint16_t stun_set_channel_bind_request(stun_buffer* buf,
const ioa_addr* peer_addr, uint16_t channel_number) {
uint16_t stun_set_channel_bind_request(stun_buffer *buf, const ioa_addr *peer_addr, uint16_t channel_number) {
return stun_set_channel_bind_request_str(buf->buf,(size_t*)(&(buf->len)), peer_addr, channel_number);
return stun_set_channel_bind_request_str(buf->buf, (size_t *)(&(buf->len)), peer_addr, channel_number);
}
void stun_set_channel_bind_response(stun_buffer* buf, stun_tid* tid, int error_code, const uint8_t *reason) {
stun_set_channel_bind_response_str(buf->buf, (size_t*)(&(buf->len)), tid, error_code, reason);
void stun_set_channel_bind_response(stun_buffer *buf, stun_tid *tid, int error_code, const uint8_t *reason) {
stun_set_channel_bind_response_str(buf->buf, (size_t *)(&(buf->len)), tid, error_code, reason);
}
////////////////////////////////////////////////////////////////
stun_attr_ref stun_attr_get_first(const stun_buffer* buf) {
stun_attr_ref stun_attr_get_first(const stun_buffer *buf) {
return stun_attr_get_first_str(buf->buf, (size_t)(buf->len));
}
stun_attr_ref stun_attr_get_next(const stun_buffer* buf, stun_attr_ref prev) {
stun_attr_ref stun_attr_get_next(const stun_buffer *buf, stun_attr_ref prev) {
return stun_attr_get_next_str(buf->buf, (size_t)(buf->len), prev);
}
int stun_attr_add(stun_buffer* buf, uint16_t attr, const char* avalue, int alen) {
return stun_attr_add_str(buf->buf, (size_t*)(&(buf->len)), attr, (const uint8_t *)avalue, alen);
int stun_attr_add(stun_buffer *buf, uint16_t attr, const char *avalue, int alen) {
return stun_attr_add_str(buf->buf, (size_t *)(&(buf->len)), attr, (const uint8_t *)avalue, alen);
}
int stun_attr_add_channel_number(stun_buffer* buf, uint16_t chnumber) {
int stun_attr_add_channel_number(stun_buffer *buf, uint16_t chnumber) {
return stun_attr_add_channel_number_str(buf->buf, (size_t *)(&(buf->len)), chnumber);
}
int stun_attr_add_addr(stun_buffer *buf,uint16_t attr_type, const ioa_addr* ca) {
return stun_attr_add_addr_str(buf->buf,(size_t*)(&(buf->len)), attr_type, ca);
int stun_attr_add_addr(stun_buffer *buf, uint16_t attr_type, const ioa_addr *ca) {
return stun_attr_add_addr_str(buf->buf, (size_t *)(&(buf->len)), attr_type, ca);
}
int stun_attr_get_addr(const stun_buffer *buf, stun_attr_ref attr, ioa_addr* ca,
const ioa_addr *default_addr) {
int stun_attr_get_addr(const stun_buffer *buf, stun_attr_ref attr, ioa_addr *ca, const ioa_addr *default_addr) {
return stun_attr_get_addr_str(buf->buf, (size_t)(buf->len), attr, ca, default_addr);
}
int stun_attr_get_first_addr(const stun_buffer *buf, uint16_t attr_type, ioa_addr* ca,
const ioa_addr *default_addr) {
int stun_attr_get_first_addr(const stun_buffer *buf, uint16_t attr_type, ioa_addr *ca, const ioa_addr *default_addr) {
return stun_attr_get_first_addr_str(buf->buf, (size_t)(buf->len), attr_type, ca, default_addr);
}
int stun_attr_add_even_port(stun_buffer* buf, uint8_t value) {
if(value) value=0x80;
return stun_attr_add(buf,STUN_ATTRIBUTE_EVEN_PORT,(const char*)&value,1);
int stun_attr_add_even_port(stun_buffer *buf, uint8_t value) {
if (value)
value = 0x80;
return stun_attr_add(buf, STUN_ATTRIBUTE_EVEN_PORT, (const char *)&value, 1);
}
uint16_t stun_attr_get_first_channel_number(const stun_buffer *buf) {
return stun_attr_get_first_channel_number_str(buf->buf, (size_t)(buf->len));
}
stun_attr_ref stun_attr_get_first_by_type(const stun_buffer* buf, uint16_t attr_type) {
stun_attr_ref stun_attr_get_first_by_type(const stun_buffer *buf, uint16_t attr_type) {
return stun_attr_get_first_by_type_str(buf->buf, (size_t)(buf->len), attr_type);
}
///////////////////////////////////////////////////////////////////////////////
void stun_set_binding_request(stun_buffer* buf) {
stun_set_binding_request_str(buf->buf, (size_t*)(&(buf->len)));
void stun_set_binding_request(stun_buffer *buf) { stun_set_binding_request_str(buf->buf, (size_t *)(&(buf->len))); }
int stun_set_binding_response(stun_buffer *buf, stun_tid *tid, const ioa_addr *reflexive_addr, int error_code,
const uint8_t *reason) {
return stun_set_binding_response_str(buf->buf, (size_t *)(&(buf->len)), tid, reflexive_addr, error_code, reason, 0, 0,
1);
}
int stun_set_binding_response(stun_buffer* buf, stun_tid* tid,
const ioa_addr *reflexive_addr, int error_code, const uint8_t *reason) {
return stun_set_binding_response_str(buf->buf, (size_t*)(&(buf->len)), tid,
reflexive_addr, error_code, reason,
0,0,1);
}
void stun_prepare_binding_request(stun_buffer *buf) { stun_set_binding_request_str(buf->buf, (size_t *)(&(buf->len))); }
void stun_prepare_binding_request(stun_buffer* buf) {
stun_set_binding_request_str(buf->buf, (size_t*)(&(buf->len)));
}
int stun_is_binding_response(const stun_buffer* buf) {
int stun_is_binding_response(const stun_buffer *buf) {
return stun_is_binding_response_str(buf->buf, (size_t)(buf->len));
}

View File

@ -40,11 +40,11 @@ extern "C" {
///////////////////////////////////////////////////////////////
typedef struct _stun_buffer {
uint8_t channel[STUN_CHANNEL_HEADER_LENGTH];
uint8_t buf[STUN_BUFFER_SIZE];
size_t len;
uint16_t offset;
uint8_t coffset;
uint8_t channel[STUN_CHANNEL_HEADER_LENGTH];
uint8_t buf[STUN_BUFFER_SIZE];
size_t len;
uint16_t offset;
uint8_t coffset;
} stun_buffer;
//////////////////////////////////////////////////////////////
@ -54,74 +54,74 @@ int stun_get_size(const stun_buffer *buf);
//////////////////////////////////////////////////////////////
void stun_tid_generate_in_message(stun_buffer* buf, stun_tid* id);
void stun_tid_from_message(const stun_buffer *buf, stun_tid* id);
void stun_tid_generate_in_message(stun_buffer *buf, stun_tid *id);
void stun_tid_from_message(const stun_buffer *buf, stun_tid *id);
///////////////////////////////////////////////////////////////
int stun_is_command_message(const stun_buffer* buf);
int stun_is_request(const stun_buffer* buf);
int stun_is_response(const stun_buffer* buf);
int stun_is_success_response(const stun_buffer* buf);
int stun_is_error_response(const stun_buffer* buf, int *err_code, uint8_t *err_msg, size_t err_msg_size);
int stun_is_indication(const stun_buffer* buf);
uint16_t stun_get_method(const stun_buffer* buf);
uint16_t stun_get_msg_type(const stun_buffer* buf);
int stun_is_command_message(const stun_buffer *buf);
int stun_is_request(const stun_buffer *buf);
int stun_is_response(const stun_buffer *buf);
int stun_is_success_response(const stun_buffer *buf);
int stun_is_error_response(const stun_buffer *buf, int *err_code, uint8_t *err_msg, size_t err_msg_size);
int stun_is_indication(const stun_buffer *buf);
uint16_t stun_get_method(const stun_buffer *buf);
uint16_t stun_get_msg_type(const stun_buffer *buf);
///////////////////////////////////////////////////////////////
void stun_init_request(uint16_t method, stun_buffer* buf);
void stun_init_indication(uint16_t method, stun_buffer* buf);
void stun_init_success_response(uint16_t method, stun_buffer* buf, stun_tid* id);
void stun_init_error_response(uint16_t method, stun_buffer* buf, uint16_t error_code, const uint8_t *reason, stun_tid* id);
void stun_init_request(uint16_t method, stun_buffer *buf);
void stun_init_indication(uint16_t method, stun_buffer *buf);
void stun_init_success_response(uint16_t method, stun_buffer *buf, stun_tid *id);
void stun_init_error_response(uint16_t method, stun_buffer *buf, uint16_t error_code, const uint8_t *reason,
stun_tid *id);
///////////////////////////////////////////////////////////////
int stun_attr_add(stun_buffer* buf, uint16_t attr, const char* avalue, int alen);
int stun_attr_add_channel_number(stun_buffer* buf, uint16_t chnumber);
int stun_attr_add_addr(stun_buffer *buf,uint16_t attr_type, const ioa_addr* ca);
int stun_attr_add(stun_buffer *buf, uint16_t attr, const char *avalue, int alen);
int stun_attr_add_channel_number(stun_buffer *buf, uint16_t chnumber);
int stun_attr_add_addr(stun_buffer *buf, uint16_t attr_type, const ioa_addr *ca);
stun_attr_ref stun_attr_get_first(const stun_buffer* buf);
stun_attr_ref stun_attr_get_first_by_type(const stun_buffer* buf, uint16_t attr_type);
stun_attr_ref stun_attr_get_next(const stun_buffer* buf, stun_attr_ref prev);
int stun_attr_get_addr(const stun_buffer *buf, stun_attr_ref attr, ioa_addr* ca, const ioa_addr *default_addr);
int stun_attr_add_even_port(stun_buffer* buf, uint8_t value);
stun_attr_ref stun_attr_get_first(const stun_buffer *buf);
stun_attr_ref stun_attr_get_first_by_type(const stun_buffer *buf, uint16_t attr_type);
stun_attr_ref stun_attr_get_next(const stun_buffer *buf, stun_attr_ref prev);
int stun_attr_get_addr(const stun_buffer *buf, stun_attr_ref attr, ioa_addr *ca, const ioa_addr *default_addr);
int stun_attr_add_even_port(stun_buffer *buf, uint8_t value);
int stun_attr_get_first_addr(const stun_buffer *buf, uint16_t attr_type, ioa_addr* ca, const ioa_addr *default_addr);
int stun_attr_get_first_addr(const stun_buffer *buf, uint16_t attr_type, ioa_addr *ca, const ioa_addr *default_addr);
uint16_t stun_attr_get_first_channel_number(const stun_buffer *buf);
///////////////////////////////////////////////////////////////
int stun_get_command_message_len(const stun_buffer* buf);
int stun_get_command_message_len(const stun_buffer *buf);
///////////////////////////////////////////////////////////////
int stun_init_channel_message(uint16_t chnumber, stun_buffer* buf, int length, int do_padding);
int stun_is_channel_message(stun_buffer* buf, uint16_t* chnumber, int is_padding_madatory);
int stun_init_channel_message(uint16_t chnumber, stun_buffer *buf, int length, int do_padding);
int stun_is_channel_message(stun_buffer *buf, uint16_t *chnumber, int is_padding_madatory);
///////////////////////////////////////////////////////////////
int stun_set_allocate_request(stun_buffer* buf, uint32_t lifetime, int af4, int af6, uint8_t transport, int mobile, const char* rt, int ep);
int stun_set_allocate_response(stun_buffer* buf, stun_tid* tid,
const ioa_addr *relayed_addr1, const ioa_addr *relayed_addr2,
const ioa_addr *reflexive_addr,
uint32_t lifetime, uint32_t max_lifetime,
int error_code, const uint8_t *reason,
uint64_t reservation_token, char *mobile_id);
int stun_set_allocate_request(stun_buffer *buf, uint32_t lifetime, int af4, int af6, uint8_t transport, int mobile,
const char *rt, int ep);
int stun_set_allocate_response(stun_buffer *buf, stun_tid *tid, const ioa_addr *relayed_addr1,
const ioa_addr *relayed_addr2, const ioa_addr *reflexive_addr, uint32_t lifetime,
uint32_t max_lifetime, int error_code, const uint8_t *reason, uint64_t reservation_token,
char *mobile_id);
///////////////////////////////////////////////////////////////
void stun_set_binding_request(stun_buffer* buf);
int stun_set_binding_response(stun_buffer* buf, stun_tid* tid,
const ioa_addr *reflexive_addr, int error_code, const uint8_t *reason);
void stun_set_binding_request(stun_buffer *buf);
int stun_set_binding_response(stun_buffer *buf, stun_tid *tid, const ioa_addr *reflexive_addr, int error_code,
const uint8_t *reason);
void stun_prepare_binding_request(stun_buffer* buf);
int stun_is_binding_response(const stun_buffer* buf);
void stun_prepare_binding_request(stun_buffer *buf);
int stun_is_binding_response(const stun_buffer *buf);
///////////////////////////////////////////////////////////////
uint16_t stun_set_channel_bind_request(stun_buffer* buf, const ioa_addr* peer_addr, uint16_t channel_number);
void stun_set_channel_bind_response(stun_buffer* buf, stun_tid* tid, int error_code, const uint8_t *reason);
uint16_t stun_set_channel_bind_request(stun_buffer *buf, const ioa_addr *peer_addr, uint16_t channel_number);
void stun_set_channel_bind_response(stun_buffer *buf, stun_tid *tid, int error_code, const uint8_t *reason);
///////////////////////////////////////////////////////////////

View File

@ -50,54 +50,52 @@
*/
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#define REPLACE_GETOPT /* use this getopt as the system getopt(3) */
#define REPLACE_GETOPT /* use this getopt as the system getopt(3) */
#ifdef REPLACE_GETOPT
int opterr = 1; /* if error message should be printed */
int optind = 1; /* index into parent argv vector */
int optopt = '?'; /* character checked for validity */
#undef optreset /* see getopt.h */
#define optreset __mingw_optreset
int optreset; /* reset getopt */
char *optarg; /* argument associated with option */
int opterr = 1; /* if error message should be printed */
int optind = 1; /* index into parent argv vector */
int optopt = '?'; /* character checked for validity */
#undef optreset /* see getopt.h */
#define optreset __mingw_optreset
int optreset; /* reset getopt */
char *optarg; /* argument associated with option */
#endif
#define PRINT_ERROR ((opterr) && (*options != ':'))
#define PRINT_ERROR ((opterr) && (*options != ':'))
#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */
#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */
#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */
#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */
#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */
#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */
/* return values */
#define BADCH (int)'?'
#define BADARG ((*options == ':') ? (int)':' : (int)'?')
#define INORDER (int)1
#define BADCH (int)'?'
#define BADARG ((*options == ':') ? (int)':' : (int)'?')
#define INORDER (int)1
#ifndef __CYGWIN__
#define __progname __argv[0]
#else
extern char __declspec(dllimport) *__progname;
extern char __declspec(dllimport) * __progname;
#endif
#ifdef __CYGWIN__
static char EMSG[] = "";
#else
#define EMSG ""
#define EMSG ""
#endif
static int getopt_internal(int, char * const *, const char *,
const struct option *, int *, int);
static int parse_long_options(char * const *, const char *,
const struct option *, int *, int);
static int getopt_internal(int, char *const *, const char *, const struct option *, int *, int);
static int parse_long_options(char *const *, const char *, const struct option *, int *, int);
static int gcd(int, int);
static void permute_args(int, int, int, char * const *);
static void permute_args(int, int, int, char *const *);
static char *place = EMSG; /* option letter processing */
@ -113,40 +111,34 @@ static const char noarg[] = "option doesn't take an argument -- %.*s";
static const char illoptchar[] = "unknown option -- %c";
static const char illoptstring[] = "unknown option -- %s";
static void
_vwarnx(const char *fmt,va_list ap)
{
(void)fprintf(stderr,"%s: ",__progname);
static void _vwarnx(const char *fmt, va_list ap) {
(void)fprintf(stderr, "%s: ", __progname);
if (fmt != NULL)
(void)vfprintf(stderr,fmt,ap);
(void)fprintf(stderr,"\n");
(void)vfprintf(stderr, fmt, ap);
(void)fprintf(stderr, "\n");
}
static void
warnx(const char *fmt,...)
{
static void warnx(const char *fmt, ...) {
va_list ap;
va_start(ap,fmt);
_vwarnx(fmt,ap);
va_start(ap, fmt);
_vwarnx(fmt, ap);
va_end(ap);
}
/*
* Compute the greatest common divisor of a and b.
*/
static int
gcd(int a, int b)
{
int c;
static int gcd(int a, int b) {
int c;
c = a % b;
while (c != 0) {
a = b;
b = c;
c = a % b;
}
c = a % b;
while (c != 0) {
a = b;
b = c;
c = a % b;
}
return (b);
return (b);
}
/*
@ -154,36 +146,33 @@ gcd(int a, int b)
* from nonopt_end to opt_end (keeping the same order of arguments
* in each block).
*/
static void
permute_args(int panonopt_start, int panonopt_end, int opt_end,
char * const *nargv)
{
int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
char *swap;
static void permute_args(int panonopt_start, int panonopt_end, int opt_end, char *const *nargv) {
int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
char *swap;
/*
* compute lengths of blocks and number and size of cycles
*/
nnonopts = panonopt_end - panonopt_start;
nopts = opt_end - panonopt_end;
ncycle = gcd(nnonopts, nopts);
cyclelen = (opt_end - panonopt_start) / ncycle;
/*
* compute lengths of blocks and number and size of cycles
*/
nnonopts = panonopt_end - panonopt_start;
nopts = opt_end - panonopt_end;
ncycle = gcd(nnonopts, nopts);
cyclelen = (opt_end - panonopt_start) / ncycle;
for (i = 0; i < ncycle; i++) {
cstart = panonopt_end+i;
pos = cstart;
for (j = 0; j < cyclelen; j++) {
if (pos >= panonopt_end)
pos -= nnonopts;
else
pos += nopts;
swap = nargv[pos];
/* LINTED const cast */
((char **) nargv)[pos] = nargv[cstart];
/* LINTED const cast */
((char **)nargv)[cstart] = swap;
}
}
for (i = 0; i < ncycle; i++) {
cstart = panonopt_end + i;
pos = cstart;
for (j = 0; j < cyclelen; j++) {
if (pos >= panonopt_end)
pos -= nnonopts;
else
pos += nopts;
swap = nargv[pos];
/* LINTED const cast */
((char **)nargv)[pos] = nargv[cstart];
/* LINTED const cast */
((char **)nargv)[cstart] = swap;
}
}
}
/*
@ -191,127 +180,116 @@ permute_args(int panonopt_start, int panonopt_end, int opt_end,
* Parse long options in argc/argv argument vector.
* Returns -1 if short_too is set and the option does not match long_options.
*/
static int
parse_long_options(char * const *nargv, const char *options,
const struct option *long_options, int *idx, int short_too)
{
char *current_argv, *has_equal;
size_t current_argv_len;
int i, ambiguous, match;
static int parse_long_options(char *const *nargv, const char *options, const struct option *long_options, int *idx,
int short_too) {
char *current_argv, *has_equal;
size_t current_argv_len;
int i, ambiguous, match;
#define IDENTICAL_INTERPRETATION(_x, _y) \
(long_options[(_x)].has_arg == long_options[(_y)].has_arg && \
long_options[(_x)].flag == long_options[(_y)].flag && \
long_options[(_x)].val == long_options[(_y)].val)
#define IDENTICAL_INTERPRETATION(_x, _y) \
(long_options[(_x)].has_arg == long_options[(_y)].has_arg && long_options[(_x)].flag == long_options[(_y)].flag && \
long_options[(_x)].val == long_options[(_y)].val)
current_argv = place;
match = -1;
ambiguous = 0;
current_argv = place;
match = -1;
ambiguous = 0;
optind++;
optind++;
if ((has_equal = strchr(current_argv, '=')) != NULL) {
/* argument found (--option=arg) */
current_argv_len = has_equal - current_argv;
has_equal++;
} else
current_argv_len = strlen(current_argv);
if ((has_equal = strchr(current_argv, '=')) != NULL) {
/* argument found (--option=arg) */
current_argv_len = has_equal - current_argv;
has_equal++;
} else
current_argv_len = strlen(current_argv);
for (i = 0; long_options[i].name; i++) {
/* find matching long option */
if (strncmp(current_argv, long_options[i].name,
current_argv_len))
continue;
for (i = 0; long_options[i].name; i++) {
/* find matching long option */
if (strncmp(current_argv, long_options[i].name, current_argv_len))
continue;
if (strlen(long_options[i].name) == current_argv_len) {
/* exact match */
match = i;
ambiguous = 0;
break;
}
/*
* If this is a known short option, don't allow
* a partial match of a single character.
*/
if (short_too && current_argv_len == 1)
continue;
if (strlen(long_options[i].name) == current_argv_len) {
/* exact match */
match = i;
ambiguous = 0;
break;
}
/*
* If this is a known short option, don't allow
* a partial match of a single character.
*/
if (short_too && current_argv_len == 1)
continue;
if (match == -1) /* partial match */
match = i;
else if (!IDENTICAL_INTERPRETATION(i, match))
ambiguous = 1;
}
if (ambiguous) {
/* ambiguous abbreviation */
if (PRINT_ERROR)
warnx(ambig, (int)current_argv_len,
current_argv);
optopt = 0;
return (BADCH);
}
if (match != -1) { /* option found */
if (long_options[match].has_arg == no_argument
&& has_equal) {
if (PRINT_ERROR)
warnx(noarg, (int)current_argv_len,
current_argv);
/*
* XXX: GNU sets optopt to val regardless of flag
*/
if (long_options[match].flag == NULL)
optopt = long_options[match].val;
else
optopt = 0;
return (BADARG);
}
if (long_options[match].has_arg == required_argument ||
long_options[match].has_arg == optional_argument) {
if (has_equal)
optarg = has_equal;
else if (long_options[match].has_arg ==
required_argument) {
/*
* optional argument doesn't use next nargv
*/
optarg = nargv[optind++];
}
}
if ((long_options[match].has_arg == required_argument)
&& (optarg == NULL)) {
/*
* Missing argument; leading ':' indicates no error
* should be generated.
*/
if (PRINT_ERROR)
warnx(recargstring,
current_argv);
/*
* XXX: GNU sets optopt to val regardless of flag
*/
if (long_options[match].flag == NULL)
optopt = long_options[match].val;
else
optopt = 0;
--optind;
return (BADARG);
}
} else { /* unknown option */
if (short_too) {
--optind;
return (-1);
}
if (PRINT_ERROR)
warnx(illoptstring, current_argv);
optopt = 0;
return (BADCH);
}
if (idx)
*idx = match;
if (long_options[match].flag) {
*long_options[match].flag = long_options[match].val;
return (0);
} else
return (long_options[match].val);
if (match == -1) /* partial match */
match = i;
else if (!IDENTICAL_INTERPRETATION(i, match))
ambiguous = 1;
}
if (ambiguous) {
/* ambiguous abbreviation */
if (PRINT_ERROR)
warnx(ambig, (int)current_argv_len, current_argv);
optopt = 0;
return (BADCH);
}
if (match != -1) { /* option found */
if (long_options[match].has_arg == no_argument && has_equal) {
if (PRINT_ERROR)
warnx(noarg, (int)current_argv_len, current_argv);
/*
* XXX: GNU sets optopt to val regardless of flag
*/
if (long_options[match].flag == NULL)
optopt = long_options[match].val;
else
optopt = 0;
return (BADARG);
}
if (long_options[match].has_arg == required_argument || long_options[match].has_arg == optional_argument) {
if (has_equal)
optarg = has_equal;
else if (long_options[match].has_arg == required_argument) {
/*
* optional argument doesn't use next nargv
*/
optarg = nargv[optind++];
}
}
if ((long_options[match].has_arg == required_argument) && (optarg == NULL)) {
/*
* Missing argument; leading ':' indicates no error
* should be generated.
*/
if (PRINT_ERROR)
warnx(recargstring, current_argv);
/*
* XXX: GNU sets optopt to val regardless of flag
*/
if (long_options[match].flag == NULL)
optopt = long_options[match].val;
else
optopt = 0;
--optind;
return (BADARG);
}
} else { /* unknown option */
if (short_too) {
--optind;
return (-1);
}
if (PRINT_ERROR)
warnx(illoptstring, current_argv);
optopt = 0;
return (BADCH);
}
if (idx)
*idx = match;
if (long_options[match].flag) {
*long_options[match].flag = long_options[match].val;
return (0);
} else
return (long_options[match].val);
#undef IDENTICAL_INTERPRETATION
}
@ -319,197 +297,185 @@ parse_long_options(char * const *nargv, const char *options,
* getopt_internal --
* Parse argc/argv argument vector. Called by user level routines.
*/
static int
getopt_internal(int nargc, char * const *nargv, const char *options,
const struct option *long_options, int *idx, int flags)
{
const char *oli; /* option letter list index */
int optchar, short_too;
static int posixly_correct = -1;
static int getopt_internal(int nargc, char *const *nargv, const char *options, const struct option *long_options,
int *idx, int flags) {
const char *oli; /* option letter list index */
int optchar, short_too;
static int posixly_correct = -1;
if (options == NULL)
return (-1);
if (options == NULL)
return (-1);
/*
* XXX Some GNU programs (like cvs) set optind to 0 instead of
* XXX using optreset. Work around this braindamage.
*/
if (optind == 0)
optind = optreset = 1;
/*
* XXX Some GNU programs (like cvs) set optind to 0 instead of
* XXX using optreset. Work around this braindamage.
*/
if (optind == 0)
optind = optreset = 1;
/*
* Disable GNU extensions if POSIXLY_CORRECT is set or options
* string begins with a '+'.
*
* CV, 2009-12-14: Check POSIXLY_CORRECT anew if optind == 0 or
* optreset != 0 for GNU compatibility.
*/
if (posixly_correct == -1 || optreset != 0)
posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
if (*options == '-')
flags |= FLAG_ALLARGS;
else if (posixly_correct || *options == '+')
flags &= ~FLAG_PERMUTE;
if (*options == '+' || *options == '-')
options++;
/*
* Disable GNU extensions if POSIXLY_CORRECT is set or options
* string begins with a '+'.
*
* CV, 2009-12-14: Check POSIXLY_CORRECT anew if optind == 0 or
* optreset != 0 for GNU compatibility.
*/
if (posixly_correct == -1 || optreset != 0)
posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
if (*options == '-')
flags |= FLAG_ALLARGS;
else if (posixly_correct || *options == '+')
flags &= ~FLAG_PERMUTE;
if (*options == '+' || *options == '-')
options++;
optarg = NULL;
if (optreset)
nonopt_start = nonopt_end = -1;
optarg = NULL;
if (optreset)
nonopt_start = nonopt_end = -1;
start:
if (optreset || !*place) { /* update scanning pointer */
optreset = 0;
if (optind >= nargc) { /* end of argument vector */
place = EMSG;
if (nonopt_end != -1) {
/* do permutation, if we have to */
permute_args(nonopt_start, nonopt_end,
optind, nargv);
optind -= nonopt_end - nonopt_start;
}
else if (nonopt_start != -1) {
/*
* If we skipped non-options, set optind
* to the first of them.
*/
optind = nonopt_start;
}
nonopt_start = nonopt_end = -1;
return (-1);
}
if (*(place = nargv[optind]) != '-' ||
(place[1] == '\0' && strchr(options, '-') == NULL)) {
place = EMSG; /* found non-option */
if (flags & FLAG_ALLARGS) {
/*
* GNU extension:
* return non-option as argument to option 1
*/
optarg = nargv[optind++];
return (INORDER);
}
if (!(flags & FLAG_PERMUTE)) {
/*
* If no permutation wanted, stop parsing
* at first non-option.
*/
return (-1);
}
/* do permutation */
if (nonopt_start == -1)
nonopt_start = optind;
else if (nonopt_end != -1) {
permute_args(nonopt_start, nonopt_end,
optind, nargv);
nonopt_start = optind -
(nonopt_end - nonopt_start);
nonopt_end = -1;
}
optind++;
/* process next argument */
goto start;
}
if (nonopt_start != -1 && nonopt_end == -1)
nonopt_end = optind;
if (optreset || !*place) { /* update scanning pointer */
optreset = 0;
if (optind >= nargc) { /* end of argument vector */
place = EMSG;
if (nonopt_end != -1) {
/* do permutation, if we have to */
permute_args(nonopt_start, nonopt_end, optind, nargv);
optind -= nonopt_end - nonopt_start;
} else if (nonopt_start != -1) {
/*
* If we skipped non-options, set optind
* to the first of them.
*/
optind = nonopt_start;
}
nonopt_start = nonopt_end = -1;
return (-1);
}
if (*(place = nargv[optind]) != '-' || (place[1] == '\0' && strchr(options, '-') == NULL)) {
place = EMSG; /* found non-option */
if (flags & FLAG_ALLARGS) {
/*
* GNU extension:
* return non-option as argument to option 1
*/
optarg = nargv[optind++];
return (INORDER);
}
if (!(flags & FLAG_PERMUTE)) {
/*
* If no permutation wanted, stop parsing
* at first non-option.
*/
return (-1);
}
/* do permutation */
if (nonopt_start == -1)
nonopt_start = optind;
else if (nonopt_end != -1) {
permute_args(nonopt_start, nonopt_end, optind, nargv);
nonopt_start = optind - (nonopt_end - nonopt_start);
nonopt_end = -1;
}
optind++;
/* process next argument */
goto start;
}
if (nonopt_start != -1 && nonopt_end == -1)
nonopt_end = optind;
/*
* If we have "-" do nothing, if "--" we are done.
*/
if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
optind++;
place = EMSG;
/*
* We found an option (--), so if we skipped
* non-options, we have to permute.
*/
if (nonopt_end != -1) {
permute_args(nonopt_start, nonopt_end,
optind, nargv);
optind -= nonopt_end - nonopt_start;
}
nonopt_start = nonopt_end = -1;
return (-1);
}
}
/*
* If we have "-" do nothing, if "--" we are done.
*/
if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
optind++;
place = EMSG;
/*
* We found an option (--), so if we skipped
* non-options, we have to permute.
*/
if (nonopt_end != -1) {
permute_args(nonopt_start, nonopt_end, optind, nargv);
optind -= nonopt_end - nonopt_start;
}
nonopt_start = nonopt_end = -1;
return (-1);
}
}
/*
* Check long options if:
* 1) we were passed some
* 2) the arg is not just "-"
* 3) either the arg starts with -- we are getopt_long_only()
*/
if (long_options != NULL && place != nargv[optind] &&
(*place == '-' || (flags & FLAG_LONGONLY))) {
short_too = 0;
if (*place == '-')
place++; /* --foo long option */
else if (*place != ':' && strchr(options, *place) != NULL)
short_too = 1; /* could be short option too */
/*
* Check long options if:
* 1) we were passed some
* 2) the arg is not just "-"
* 3) either the arg starts with -- we are getopt_long_only()
*/
if (long_options != NULL && place != nargv[optind] && (*place == '-' || (flags & FLAG_LONGONLY))) {
short_too = 0;
if (*place == '-')
place++; /* --foo long option */
else if (*place != ':' && strchr(options, *place) != NULL)
short_too = 1; /* could be short option too */
optchar = parse_long_options(nargv, options, long_options,
idx, short_too);
if (optchar != -1) {
place = EMSG;
return (optchar);
}
}
optchar = parse_long_options(nargv, options, long_options, idx, short_too);
if (optchar != -1) {
place = EMSG;
return (optchar);
}
}
if ((optchar = (int)*place++) == (int)':' ||
(optchar == (int)'-' && *place != '\0') ||
(oli = strchr(options, optchar)) == NULL) {
/*
* If the user specified "-" and '-' isn't listed in
* options, return -1 (non-option) as per POSIX.
* Otherwise, it is an unknown option character (or ':').
*/
if (optchar == (int)'-' && *place == '\0')
return (-1);
if (!*place)
++optind;
if (PRINT_ERROR)
warnx(illoptchar, optchar);
optopt = optchar;
return (BADCH);
}
if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
/* -W long-option */
if (*place) /* no space */
/* NOTHING */;
else if (++optind >= nargc) { /* no arg */
place = EMSG;
if (PRINT_ERROR)
warnx(recargchar, optchar);
optopt = optchar;
return (BADARG);
} else /* white space */
place = nargv[optind];
optchar = parse_long_options(nargv, options, long_options,
idx, 0);
place = EMSG;
return (optchar);
}
if (*++oli != ':') { /* doesn't take argument */
if (!*place)
++optind;
} else { /* takes (optional) argument */
optarg = NULL;
if (*place) /* no white space */
optarg = place;
else if (oli[1] != ':') { /* arg not optional */
if (++optind >= nargc) { /* no arg */
place = EMSG;
if (PRINT_ERROR)
warnx(recargchar, optchar);
optopt = optchar;
return (BADARG);
} else
optarg = nargv[optind];
}
place = EMSG;
++optind;
}
/* dump back option letter */
return (optchar);
if ((optchar = (int)*place++) == (int)':' || (optchar == (int)'-' && *place != '\0') ||
(oli = strchr(options, optchar)) == NULL) {
/*
* If the user specified "-" and '-' isn't listed in
* options, return -1 (non-option) as per POSIX.
* Otherwise, it is an unknown option character (or ':').
*/
if (optchar == (int)'-' && *place == '\0')
return (-1);
if (!*place)
++optind;
if (PRINT_ERROR)
warnx(illoptchar, optchar);
optopt = optchar;
return (BADCH);
}
if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
/* -W long-option */
if (*place) /* no space */
/* NOTHING */;
else if (++optind >= nargc) { /* no arg */
place = EMSG;
if (PRINT_ERROR)
warnx(recargchar, optchar);
optopt = optchar;
return (BADARG);
} else /* white space */
place = nargv[optind];
optchar = parse_long_options(nargv, options, long_options, idx, 0);
place = EMSG;
return (optchar);
}
if (*++oli != ':') { /* doesn't take argument */
if (!*place)
++optind;
} else { /* takes (optional) argument */
optarg = NULL;
if (*place) /* no white space */
optarg = place;
else if (oli[1] != ':') { /* arg not optional */
if (++optind >= nargc) { /* no arg */
place = EMSG;
if (PRINT_ERROR)
warnx(recargchar, optchar);
optopt = optchar;
return (BADARG);
} else
optarg = nargv[optind];
}
place = EMSG;
++optind;
}
/* dump back option letter */
return (optchar);
}
#ifdef REPLACE_GETOPT
@ -519,19 +485,17 @@ start:
*
* [eventually this will replace the BSD getopt]
*/
int
getopt(int nargc, char * const *nargv, const char *options)
{
int getopt(int nargc, char *const *nargv, const char *options) {
/*
* We don't pass FLAG_PERMUTE to getopt_internal() since
* the BSD getopt(3) (unlike GNU) has never done this.
*
* Furthermore, since many privileged programs call getopt()
* before dropping privileges it makes sense to keep things
* as simple (and bug-free) as possible.
*/
return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
/*
* We don't pass FLAG_PERMUTE to getopt_internal() since
* the BSD getopt(3) (unlike GNU) has never done this.
*
* Furthermore, since many privileged programs call getopt()
* before dropping privileges it makes sense to keep things
* as simple (and bug-free) as possible.
*/
return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
}
#endif /* REPLACE_GETOPT */
@ -539,24 +503,16 @@ getopt(int nargc, char * const *nargv, const char *options)
* getopt_long --
* Parse argc/argv argument vector.
*/
int
getopt_long(int nargc, char * const *nargv, const char *options,
const struct option *long_options, int *idx)
{
int getopt_long(int nargc, char *const *nargv, const char *options, const struct option *long_options, int *idx) {
return (getopt_internal(nargc, nargv, options, long_options, idx,
FLAG_PERMUTE));
return (getopt_internal(nargc, nargv, options, long_options, idx, FLAG_PERMUTE));
}
/*
* getopt_long_only --
* Parse argc/argv argument vector.
*/
int
getopt_long_only(int nargc, char * const *nargv, const char *options,
const struct option *long_options, int *idx)
{
int getopt_long_only(int nargc, char *const *nargv, const char *options, const struct option *long_options, int *idx) {
return (getopt_internal(nargc, nargv, options, long_options, idx,
FLAG_PERMUTE|FLAG_LONGONLY));
return (getopt_internal(nargc, nargv, options, long_options, idx, FLAG_PERMUTE | FLAG_LONGONLY));
}

View File

@ -4,9 +4,9 @@
* This file has no copyright assigned and is placed in the Public Domain.
* This file is a part of the w64 mingw-runtime package.
*
* The w64 mingw-runtime package and its code is distributed in the hope that it
* will be useful but WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESSED OR
* IMPLIED ARE HEREBY DISCLAIMED. This includes but is not limited to
* The w64 mingw-runtime package and its code is distributed in the hope that it
* will be useful but WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESSED OR
* IMPLIED ARE HEREBY DISCLAIMED. This includes but is not limited to
* warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
@ -15,28 +15,28 @@
/* All the headers include this file. */
#include <crtdefs.h>
#if defined( WINGETOPT_SHARED_LIB )
# if defined( BUILDING_WINGETOPT_DLL )
# define WINGETOPT_API __declspec(dllexport)
# else
# define WINGETOPT_API __declspec(dllimport)
# endif
#if defined(WINGETOPT_SHARED_LIB)
#if defined(BUILDING_WINGETOPT_DLL)
#define WINGETOPT_API __declspec(dllexport)
#else
# define WINGETOPT_API
#define WINGETOPT_API __declspec(dllimport)
#endif
#else
#define WINGETOPT_API
#endif
#ifdef __cplusplus
extern "C" {
#endif
WINGETOPT_API extern int optind; /* index of first non-option in argv */
WINGETOPT_API extern int optopt; /* single option character, as parsed */
WINGETOPT_API extern int opterr; /* flag to enable built-in diagnostics... */
/* (user may set to zero, to suppress) */
WINGETOPT_API extern int optind; /* index of first non-option in argv */
WINGETOPT_API extern int optopt; /* single option character, as parsed */
WINGETOPT_API extern int opterr; /* flag to enable built-in diagnostics... */
/* (user may set to zero, to suppress) */
WINGETOPT_API extern char *optarg; /* pointer to argument of current option */
WINGETOPT_API extern char *optarg; /* pointer to argument of current option */
extern int getopt(int nargc, char * const *nargv, const char *options);
extern int getopt(int nargc, char *const *nargv, const char *options);
#ifdef _BSD_SOURCE
/*
@ -45,7 +45,7 @@ extern int getopt(int nargc, char * const *nargv, const char *options);
* proclaim their BSD heritage, before including this header; however,
* to maintain portability, developers are advised to avoid it.
*/
# define optreset __mingw_optreset
#define optreset __mingw_optreset
extern int optreset;
#endif
#ifdef __cplusplus
@ -69,25 +69,23 @@ extern int optreset;
extern "C" {
#endif
struct option /* specification for a long form option... */
struct option /* specification for a long form option... */
{
const char *name; /* option name, without leading hyphens */
int has_arg; /* does it take an argument? */
int *flag; /* where to save its status, or NULL */
int val; /* its associated status value */
const char *name; /* option name, without leading hyphens */
int has_arg; /* does it take an argument? */
int *flag; /* where to save its status, or NULL */
int val; /* its associated status value */
};
enum /* permitted values for its `has_arg' field... */
{
no_argument = 0, /* option never takes an argument */
required_argument, /* option always requires an argument */
optional_argument /* option may take an argument */
enum /* permitted values for its `has_arg' field... */
{ no_argument = 0, /* option never takes an argument */
required_argument, /* option always requires an argument */
optional_argument /* option may take an argument */
};
extern int getopt_long(int nargc, char * const *nargv, const char *options,
const struct option *long_options, int *idx);
extern int getopt_long_only(int nargc, char * const *nargv, const char *options,
const struct option *long_options, int *idx);
extern int getopt_long(int nargc, char *const *nargv, const char *options, const struct option *long_options, int *idx);
extern int getopt_long_only(int nargc, char *const *nargv, const char *options, const struct option *long_options,
int *idx);
/*
* Previous MinGW implementation had...
*/
@ -95,7 +93,7 @@ extern int getopt_long_only(int nargc, char * const *nargv, const char *options,
/*
* ...for the long form API only; keep this for compatibility.
*/
# define HAVE_DECL_GETOPT 1
#define HAVE_DECL_GETOPT 1
#endif
#ifdef __cplusplus

File diff suppressed because it is too large Load Diff

View File

@ -32,456 +32,441 @@
#include <unistd.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <getopt.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "ns_turn_utils.h"
#include "apputils.h"
#include "ns_turn_utils.h"
#include "stun_buffer.h"
////////////////////////////////////////////////////
#define OAUTH_TOKEN_SIZE 1000 //TODO: find insted of 1000 the real max of encoded token length
#define OAUTH_TOKEN_SIZE 1000 // TODO: find insted of 1000 the real max of encoded token length
#define OAUTH_MAC_KEY_SIZE 32
#define OAUTH_LTK_ID_SIZE 32
#define OAUTH_LTK_SIZE 32
#define OAUTH_LTK_BASE64ENCODED_SIZE 44
#define OAUTH_TOKEN_LIFETIME 3600
#define OAUTH_AS_RS_ALG_SIZE 7
#define OAUTH_SERVER_NAME_SIZE 255
#define OAUTH_GCM_NONCE_BASE64ENCODED_SIZE 16
#define OAUTH_AS_RS_ALG_SIZE 7
#define OAUTH_SERVER_NAME_SIZE 255
#define OAUTH_GCM_NONCE_BASE64ENCODED_SIZE 16
#define OAUTH_HMAC_ALG_SIZE 20
static int setup_ikm_key(const char *kid, const char *ikm_key, const turn_time_t key_timestamp,
const turn_time_t key_lifetime, const char *as_rs_alg, oauth_key *key) {
static int setup_ikm_key(const char *kid,
const char *ikm_key,
const turn_time_t key_timestamp,
const turn_time_t key_lifetime,
const char *as_rs_alg,
oauth_key *key) {
memset(key, 0, sizeof(*key));
memset(key, 0, sizeof(*key));
oauth_key_data okd;
memset(&okd, 0, sizeof(okd));
oauth_key_data okd;
memset(&okd, 0, sizeof(okd));
{
oauth_key_data_raw okdr;
memset(&okdr, 0, sizeof(okdr));
{
oauth_key_data_raw okdr;
memset(&okdr, 0, sizeof(okdr));
STRCPY(okdr.kid, kid);
STRCPY(okdr.ikm_key, ikm_key);
STRCPY(okdr.as_rs_alg, as_rs_alg);
okdr.timestamp = key_timestamp;
okdr.lifetime = key_lifetime;
STRCPY(okdr.kid,kid);
STRCPY(okdr.ikm_key,ikm_key);
STRCPY(okdr.as_rs_alg,as_rs_alg);
okdr.timestamp = key_timestamp;
okdr.lifetime = key_lifetime;
convert_oauth_key_data_raw(&okdr, &okd);
}
convert_oauth_key_data_raw(&okdr, &okd);
}
char err_msg[1025] = "\0";
size_t err_msg_size = sizeof(err_msg) - 1;
char err_msg[1025] = "\0";
size_t err_msg_size = sizeof(err_msg) - 1;
if (convert_oauth_key_data(&okd, key, err_msg, err_msg_size) < 0) {
fprintf(stderr, "%s\n", err_msg);
return -1;
}
if (convert_oauth_key_data(&okd, key, err_msg, err_msg_size) < 0) {
fprintf(stderr, "%s\n", err_msg);
return -1;
}
return 0;
return 0;
}
static int encode_token(const char *server_name, const char *gcm_nonce, const char *mac_key,
const uint64_t token_timestamp, const uint32_t token_lifetime, const oauth_key key,
char *base64encoded_etoken) {
oauth_token ot;
memset(&ot, 0, sizeof(ot));
static int encode_token(const char* server_name,
const char* gcm_nonce,
const char* mac_key,
const uint64_t token_timestamp,
const uint32_t token_lifetime,
const oauth_key key,
char* base64encoded_etoken) {
const size_t mac_key_length = strlen(mac_key);
ot.enc_block.key_length = (uint16_t)mac_key_length;
STRCPY(ot.enc_block.mac_key, mac_key);
ot.enc_block.timestamp = token_timestamp;
ot.enc_block.lifetime = token_lifetime;
encoded_oauth_token etoken;
memset(&etoken, 0, sizeof(etoken));
oauth_token ot;
memset(&ot, 0, sizeof(ot));
// TODO: avoid this hack
if (!*gcm_nonce)
gcm_nonce = NULL;
const size_t mac_key_length=strlen(mac_key);
ot.enc_block.key_length = (uint16_t)mac_key_length;
STRCPY(ot.enc_block.mac_key,mac_key);
ot.enc_block.timestamp = token_timestamp;
ot.enc_block.lifetime = token_lifetime;
if (encode_oauth_token((const uint8_t *)server_name, &etoken, &key, &ot, (const uint8_t *)gcm_nonce) < 0) {
fprintf(stderr, "%s: cannot encode oauth token\n", __FUNCTION__);
return -1;
}
encoded_oauth_token etoken;
memset(&etoken, 0, sizeof(etoken));
size_t base64encoded_etoken_length;
char *tmp = base64_encode((unsigned char *)(etoken.token), etoken.size, &base64encoded_etoken_length);
STRCPY(base64encoded_etoken, tmp);
free(tmp);
// TODO: avoid this hack
if (!*gcm_nonce) gcm_nonce=NULL;
if (encode_oauth_token((const uint8_t *) server_name, &etoken, &key, &ot,(const uint8_t *) gcm_nonce) < 0) {
fprintf(stderr, "%s: cannot encode oauth token\n",
__FUNCTION__);
return -1;
}
size_t base64encoded_etoken_length;
char *tmp=base64_encode((unsigned char *)(etoken.token), etoken.size, &base64encoded_etoken_length);
STRCPY(base64encoded_etoken,tmp);
free(tmp);
return 0;
return 0;
}
static int validate_decode_token(const char* server_name,
const oauth_key key,
const char* base64encoded_etoken, oauth_token* dot) {
static int validate_decode_token(const char *server_name, const oauth_key key, const char *base64encoded_etoken,
oauth_token *dot) {
memset((dot), 0, sizeof(*dot));
memset((dot), 0, sizeof(*dot));
encoded_oauth_token etoken;
memset(&etoken, 0, sizeof(etoken));
encoded_oauth_token etoken;
memset(&etoken, 0, sizeof(etoken));
const size_t base64encoded_etoken_length=strlen(base64encoded_etoken);
unsigned char *tmp = base64_decode(base64encoded_etoken,base64encoded_etoken_length,&etoken.size);
memcpy(etoken.token,tmp,etoken.size);
free(tmp);
if (decode_oauth_token((const uint8_t *) server_name, &etoken, &key, dot) < 0) {
fprintf(stderr, "%s: cannot decode oauth token\n",
__FUNCTION__);
return -1;
} else {
return 0;
};
const size_t base64encoded_etoken_length = strlen(base64encoded_etoken);
unsigned char *tmp = base64_decode(base64encoded_etoken, base64encoded_etoken_length, &etoken.size);
memcpy(etoken.token, tmp, etoken.size);
free(tmp);
if (decode_oauth_token((const uint8_t *)server_name, &etoken, &key, dot) < 0) {
fprintf(stderr, "%s: cannot decode oauth token\n", __FUNCTION__);
return -1;
} else {
return 0;
};
}
static void print_token_body(oauth_token* dot) {
printf("\n");
printf("Token non-encrpyted body:\n");
printf("{\n");
size_t base64encoded_nonce_length;
char *base64encoded_nonce = base64_encode((unsigned char *)dot->enc_block.nonce, dot->enc_block.nonce_length,&base64encoded_nonce_length);
printf(" nonce: %s\n", base64encoded_nonce);
printf(" nonce length: %d\n", (int) dot->enc_block.nonce_length);
free(base64encoded_nonce);
printf("Token encrpyted body:\n");
printf("{\n");
printf(" mac key: %s\n", (char*) dot->enc_block.mac_key);
printf(" mac key length: %d\n", (int) dot->enc_block.key_length);
time_t time=dot->enc_block.timestamp>>16;
unsigned msec=(dot->enc_block.timestamp & 0xFFFF)*64;
printf(" timestamp:\n");
printf(" unixtime: %u (localtime: %s )", (unsigned int)time, ctime(&time));
printf(" msec:%u\n", msec);
printf(" lifetime: %lu\n", (unsigned long) dot->enc_block.lifetime);
printf("}\n");
static void print_token_body(oauth_token *dot) {
printf("\n");
printf("Token non-encrpyted body:\n");
printf("{\n");
size_t base64encoded_nonce_length;
char *base64encoded_nonce =
base64_encode((unsigned char *)dot->enc_block.nonce, dot->enc_block.nonce_length, &base64encoded_nonce_length);
printf(" nonce: %s\n", base64encoded_nonce);
printf(" nonce length: %d\n", (int)dot->enc_block.nonce_length);
free(base64encoded_nonce);
printf("Token encrpyted body:\n");
printf("{\n");
printf(" mac key: %s\n", (char *)dot->enc_block.mac_key);
printf(" mac key length: %d\n", (int)dot->enc_block.key_length);
time_t time = dot->enc_block.timestamp >> 16;
unsigned msec = (dot->enc_block.timestamp & 0xFFFF) * 64;
printf(" timestamp:\n");
printf(" unixtime: %u (localtime: %s )", (unsigned int)time, ctime(&time));
printf(" msec:%u\n", msec);
printf(" lifetime: %lu\n", (unsigned long)dot->enc_block.lifetime);
printf("}\n");
}
//////////////// local definitions /////////////////
const char Usage[] =
"Usage: oauth [ -e / -d ] [options]\n"
"Options:\n"
"\n"
" -h, --help usage\n\n"
" -v, --verbose verbose mode\n\n"
" -e, --encrypt encrypt token\n"
" -d, --decrypt decrypt validate token\n\n"
" -i, --server-name server name (max. 255 char)\n"
" -j, --auth-key-id Auth key id (max. 32 char)\n"
" -k, --auth-key base64 encoded Auth key\n"
" -l --auth-key-timestamp Auth key timestamp (sec since epoch)\n"
" -m, --auth-key-lifetime Auth key lifetime in sec\n"
" -n, --auth-key-as-rs-alg Authorization Server(AS) - Resource Server (RS) encryption algorithm\n"
" -o, --token-nonce base64 encoded nonce base64(12 octet) = 16 char\n"
" -p, --token-mac-key base64 encoded MAC key base64(32 octet) = 44 char\n"
" -q, --token-timestamp timestamp in format 64 bit unsigned (Native format - Unix),\n"
" so 48 bit for secs since epoch UTC + 16 bit for 1/64000 fractions of a second.\n"
" e.g.: the actual unixtimestamp 16 bit left shifted. (Default: actual gmtime)\n"
" -r, --token-lifetime lifetime in sec (Default: 3600)\n"
" -t, --token base64 encoded encrypted token for validation and decryption\n"
" -u, --hmac-alg stun client hmac algorithm\n";
"Usage: oauth [ -e / -d ] [options]\n"
"Options:\n"
"\n"
" -h, --help usage\n\n"
" -v, --verbose verbose mode\n\n"
" -e, --encrypt encrypt token\n"
" -d, --decrypt decrypt validate token\n\n"
" -i, --server-name server name (max. 255 char)\n"
" -j, --auth-key-id Auth key id (max. 32 char)\n"
" -k, --auth-key base64 encoded Auth key\n"
" -l --auth-key-timestamp Auth key timestamp (sec since epoch)\n"
" -m, --auth-key-lifetime Auth key lifetime in sec\n"
" -n, --auth-key-as-rs-alg Authorization Server(AS) - Resource Server (RS) encryption algorithm\n"
" -o, --token-nonce base64 encoded nonce base64(12 octet) = 16 char\n"
" -p, --token-mac-key base64 encoded MAC key base64(32 octet) = 44 char\n"
" -q, --token-timestamp timestamp in format 64 bit unsigned (Native format - Unix),\n"
" so 48 bit for secs since epoch UTC + 16 bit for 1/64000 fractions of a "
"second.\n"
" e.g.: the actual unixtimestamp 16 bit left shifted. (Default: actual "
"gmtime)\n"
" -r, --token-lifetime lifetime in sec (Default: 3600)\n"
" -t, --token base64 encoded encrypted token for validation and decryption\n"
" -u, --hmac-alg stun client hmac algorithm\n";
//////////////////////////////////////////////////
int main(int argc, char **argv)
{
int main(int argc, char **argv) {
oauth_key key;
//init vars with default values
char gcm_nonce[OAUTH_GCM_NONCE_SIZE+1]="";
// init vars with default values
char gcm_nonce[OAUTH_GCM_NONCE_SIZE + 1] = "";
char mac_key[OAUTH_MAC_KEY_SIZE+1]="";
char mac_key[OAUTH_MAC_KEY_SIZE + 1] = "";
time_t current_time = time(NULL);
struct tm* gmt = gmtime(&current_time);
struct tm *gmt = gmtime(&current_time);
uint64_t token_timestamp = (unsigned long long)mktime(gmt) << 16;
uint32_t token_lifetime = OAUTH_TOKEN_LIFETIME;
//oauth_key
char kid[OAUTH_LTK_ID_SIZE+1] = "";
char base64encoded_ltk[OAUTH_LTK_BASE64ENCODED_SIZE+1]="";
// oauth_key
char kid[OAUTH_LTK_ID_SIZE + 1] = "";
char base64encoded_ltk[OAUTH_LTK_BASE64ENCODED_SIZE + 1] = "";
turn_time_t key_timestamp = 0;
turn_time_t key_lifetime = 0;
char as_rs_alg[OAUTH_AS_RS_ALG_SIZE+1]="A256GCM";
char server_name[OAUTH_SERVER_NAME_SIZE+1] = "";
char as_rs_alg[OAUTH_AS_RS_ALG_SIZE + 1] = "A256GCM";
char server_name[OAUTH_SERVER_NAME_SIZE + 1] = "";
char base64encoded_etoken[OAUTH_TOKEN_SIZE]="";
char base64encoded_etoken[OAUTH_TOKEN_SIZE] = "";
//TODO: replace SHA1 with an option. Actualy both big browser chrome and mozilla supports AFAIU implemented only SHA1.
char hmac_alg[OAUTH_HMAC_ALG_SIZE+1]="HMAC-SHA1";
// TODO: replace SHA1 with an option. Actualy both big browser chrome and mozilla supports AFAIU implemented only
// SHA1.
char hmac_alg[OAUTH_HMAC_ALG_SIZE + 1] = "HMAC-SHA1";
static int verbose_flag=0;
static int encrypt_flag=0;
static int decrypt_flag=0;
static int verbose_flag = 0;
static int encrypt_flag = 0;
static int decrypt_flag = 0;
static struct option long_options[] =
{
/* These options set a flag. */
{"verbose", no_argument, &verbose_flag, 1},
{"encrypt", no_argument, &encrypt_flag, 1},
{"decrypt", no_argument, &decrypt_flag, 1},
{"help", no_argument, 0, 'h'},
{"server-name", required_argument, 0, 'i'},
{"auth-key-id", required_argument, 0, 'j'},
{"auth-key", required_argument, 0, 'k'},
{"auth-key-timestamp", required_argument, 0, 'l'},
{"auth-key-lifetime", required_argument, 0, 'm'},
{"auth-key-as-rs-alg", required_argument, 0, 'n'},
{"token-nonce", required_argument, 0, 'o'},
{"token-mac-key", required_argument, 0, 'p'},
{"token-timestamp", required_argument, 0, 'q'},
{"token-lifetime", required_argument, 0, 'r'},
{"token", required_argument, 0, 't'},
{"hmac-alg", required_argument, 0, 'u'},
{0, 0, 0, 0}
};
static struct option long_options[] = {/* These options set a flag. */
{"verbose", no_argument, &verbose_flag, 1},
{"encrypt", no_argument, &encrypt_flag, 1},
{"decrypt", no_argument, &decrypt_flag, 1},
{"help", no_argument, 0, 'h'},
{"server-name", required_argument, 0, 'i'},
{"auth-key-id", required_argument, 0, 'j'},
{"auth-key", required_argument, 0, 'k'},
{"auth-key-timestamp", required_argument, 0, 'l'},
{"auth-key-lifetime", required_argument, 0, 'm'},
{"auth-key-as-rs-alg", required_argument, 0, 'n'},
{"token-nonce", required_argument, 0, 'o'},
{"token-mac-key", required_argument, 0, 'p'},
{"token-timestamp", required_argument, 0, 'q'},
{"token-lifetime", required_argument, 0, 'r'},
{"token", required_argument, 0, 't'},
{"hmac-alg", required_argument, 0, 'u'},
{0, 0, 0, 0}};
/* getopt_long stores the option index here. */
int option_index = 0;
//tmp vars
size_t nonce_size=0;
// tmp vars
size_t nonce_size = 0;
char *nonce_val;
size_t mac_key_size;
char *mac_key_val;
int i;
int c=0;
int c = 0;
set_logfile("stdout");
set_no_stdout_log(1);
set_system_parameters(0);
while ((c = getopt_long(argc, argv, "hvedi:j:k:l:m:n:o:p:q:r:t:u:",long_options, &option_index)) != -1) {
switch(c) {
while ((c = getopt_long(argc, argv, "hvedi:j:k:l:m:n:o:p:q:r:t:u:", long_options, &option_index)) != -1) {
switch (c) {
case 'h':
fprintf(stderr, "%s\n", Usage);
exit(1);
exit(1);
break;
case 'v':
verbose_flag=1;
verbose_flag = 1;
break;
case 'e':
encrypt_flag=1;
encrypt_flag = 1;
break;
case 'd':
decrypt_flag=1;
decrypt_flag = 1;
break;
case 'i':
//server-name
if ( strlen(optarg) <= OAUTH_SERVER_NAME_SIZE ) {
STRCPY(server_name,optarg);
// server-name
if (strlen(optarg) <= OAUTH_SERVER_NAME_SIZE) {
STRCPY(server_name, optarg);
} else {
fprintf(stderr,"Server-name must not exceed %d!\n", OAUTH_LTK_ID_SIZE );
fprintf(stderr, "Server-name must not exceed %d!\n", OAUTH_LTK_ID_SIZE);
exit(1);
}
break;
case 'j':
//auth-key-id
if ( strlen(optarg) <= OAUTH_LTK_ID_SIZE ) {
STRCPY(kid,optarg);
case 'j':
// auth-key-id
if (strlen(optarg) <= OAUTH_LTK_ID_SIZE) {
STRCPY(kid, optarg);
} else {
fprintf(stderr,"Key ID must not exceed %d!\n", OAUTH_LTK_ID_SIZE );
fprintf(stderr, "Key ID must not exceed %d!\n", OAUTH_LTK_ID_SIZE);
exit(1);
}
break;
case 'k':
//auth-key
if ( strlen(optarg) <= OAUTH_LTK_BASE64ENCODED_SIZE ) {
STRCPY(base64encoded_ltk,optarg);
// auth-key
if (strlen(optarg) <= OAUTH_LTK_BASE64ENCODED_SIZE) {
STRCPY(base64encoded_ltk, optarg);
} else {
fprintf(stderr,"Key must not exceed %d!\n", OAUTH_LTK_BASE64ENCODED_SIZE );
fprintf(stderr, "Key must not exceed %d!\n", OAUTH_LTK_BASE64ENCODED_SIZE);
exit(1);
}
break;
case 'l':
//auth-key-timestamp
// auth-key-timestamp
key_timestamp = atoi(optarg);
break;
case 'm':
//auth-key-lifetime
key_lifetime=atoi(optarg);
// auth-key-lifetime
key_lifetime = atoi(optarg);
break;
case 'n':
//auth-key-as-rs-alg
if ( strlen(optarg) <= OAUTH_AS_RS_ALG_SIZE ) {
STRCPY(as_rs_alg,optarg);
// auth-key-as-rs-alg
if (strlen(optarg) <= OAUTH_AS_RS_ALG_SIZE) {
STRCPY(as_rs_alg, optarg);
} else {
fprintf(stderr,"AS-RS Alg must not exceed %d!\n", OAUTH_AS_RS_ALG_SIZE );
fprintf(stderr, "AS-RS Alg must not exceed %d!\n", OAUTH_AS_RS_ALG_SIZE);
exit(1);
}
break;
case 'o':
//token-nonce
nonce_val = (char*)base64_decode(optarg,strlen(optarg),&nonce_size);
if (nonce_size > OAUTH_GCM_NONCE_SIZE){
nonce_size=OAUTH_GCM_NONCE_SIZE;
}
strncpy(gcm_nonce,nonce_val,nonce_size);
gcm_nonce[ nonce_size ]='\0';
// token-nonce
nonce_val = (char *)base64_decode(optarg, strlen(optarg), &nonce_size);
if (nonce_size > OAUTH_GCM_NONCE_SIZE) {
nonce_size = OAUTH_GCM_NONCE_SIZE;
}
strncpy(gcm_nonce, nonce_val, nonce_size);
gcm_nonce[nonce_size] = '\0';
break;
case 'p':
//token-mac-key
mac_key_val = (char*)base64_decode(optarg,strlen(optarg),&mac_key_size);
if (mac_key_size > OAUTH_MAC_KEY_SIZE){
mac_key_size=OAUTH_MAC_KEY_SIZE;
}
strncpy(mac_key,mac_key_val,mac_key_size);
mac_key[mac_key_size]='\0';
// token-mac-key
mac_key_val = (char *)base64_decode(optarg, strlen(optarg), &mac_key_size);
if (mac_key_size > OAUTH_MAC_KEY_SIZE) {
mac_key_size = OAUTH_MAC_KEY_SIZE;
}
strncpy(mac_key, mac_key_val, mac_key_size);
mac_key[mac_key_size] = '\0';
break;
case 'q':
//token-timestamp
token_timestamp=strtoull(optarg,0,10);
// token-timestamp
token_timestamp = strtoull(optarg, 0, 10);
break;
case 'r':
//token-lifetime
token_lifetime=atoi(optarg);
// token-lifetime
token_lifetime = atoi(optarg);
break;
case 't':
if ( strlen(optarg) <= OAUTH_TOKEN_SIZE ) {
STRCPY(base64encoded_etoken,optarg);
if (strlen(optarg) <= OAUTH_TOKEN_SIZE) {
STRCPY(base64encoded_etoken, optarg);
} else {
fprintf(stderr,"base64 encoded encrypted token must not exceed %d!\n", OAUTH_TOKEN_SIZE );
fprintf(stderr, "base64 encoded encrypted token must not exceed %d!\n", OAUTH_TOKEN_SIZE);
exit(1);
}
break;
case 'u':
//hmac-alg
if ( strlen(optarg) <= OAUTH_HMAC_ALG_SIZE ) {
STRCPY(hmac_alg,optarg);
// hmac-alg
if (strlen(optarg) <= OAUTH_HMAC_ALG_SIZE) {
STRCPY(hmac_alg, optarg);
} else {
fprintf(stderr,"STUN client HMAC Alg must not exceed %d!\n", OAUTH_HMAC_ALG_SIZE );
fprintf(stderr, "STUN client HMAC Alg must not exceed %d!\n", OAUTH_HMAC_ALG_SIZE);
exit(1);
}
break;
default:
fprintf(stderr,"%s\n", Usage);
fprintf(stderr, "%s\n", Usage);
exit(1);
break;
}
}
for (i = optind; i < argc; i++)
printf ("Non-option argument %s\n", argv[i]);
printf("Non-option argument %s\n", argv[i]);
if(optind>argc) {
if (optind > argc) {
fprintf(stderr, "%s\n", Usage);
exit(-1);
}
if (!(encrypt_flag || decrypt_flag)){
fprintf(stderr, "Use either encrypt or decrypt.\nPlease use -h or --help for the detailed help\n");
exit(-1);
if (!(encrypt_flag || decrypt_flag)) {
fprintf(stderr, "Use either encrypt or decrypt.\nPlease use -h or --help for the detailed help\n");
exit(-1);
}
//check if we have required params
//TODO: more compact warnning handling
if (encrypt_flag || decrypt_flag){
if (strlen(server_name) == 0) {
fprintf(stderr, "For encode/decode --server-name/-i is mandatory \n");
exit(-1);
}
if (strlen(kid) == 0){
fprintf(stderr, "For encode/decode --auth-key-id/-j is mandatory \n");
exit(-1);
}
if (strlen(base64encoded_ltk) == 0){
fprintf(stderr, "For encode/decode --auth-key/-k is mandatory \n");
exit(-1);
}
if (key_timestamp == 0){
fprintf(stderr, "For encode/decode --auth-key-timestamp/-l is mandatory \n");
exit(-1);
}
if (key_lifetime == 0){
fprintf(stderr, "For encode/decode --auth-key-lifetime/-m is mandatory \n");
exit(-1);
// check if we have required params
// TODO: more compact warnning handling
if (encrypt_flag || decrypt_flag) {
if (strlen(server_name) == 0) {
fprintf(stderr, "For encode/decode --server-name/-i is mandatory \n");
exit(-1);
}
if (encrypt_flag && strlen(mac_key) == 0) {
fprintf(stderr, "For encode --token-mac-key/-p is mandatory \n");
exit(-1);
if (strlen(kid) == 0) {
fprintf(stderr, "For encode/decode --auth-key-id/-j is mandatory \n");
exit(-1);
}
if (!encrypt_flag && decrypt_flag && strlen(base64encoded_etoken) == 0) {
fprintf(stderr, "For decode --token/-t is mandatory \n");
exit(-1);
if (strlen(base64encoded_ltk) == 0) {
fprintf(stderr, "For encode/decode --auth-key/-k is mandatory \n");
exit(-1);
}
if (key_timestamp == 0) {
fprintf(stderr, "For encode/decode --auth-key-timestamp/-l is mandatory \n");
exit(-1);
}
if (key_lifetime == 0) {
fprintf(stderr, "For encode/decode --auth-key-lifetime/-m is mandatory \n");
exit(-1);
}
if (encrypt_flag && strlen(mac_key) == 0) {
fprintf(stderr, "For encode --token-mac-key/-p is mandatory \n");
exit(-1);
}
if (!encrypt_flag && decrypt_flag && strlen(base64encoded_etoken) == 0) {
fprintf(stderr, "For decode --token/-t is mandatory \n");
exit(-1);
}
// Expiry warnings
if ( (unsigned long long)key_timestamp<<16 > token_timestamp +((unsigned long long)token_lifetime << 16) ) {
fprintf(stderr,"\nWARNING: Token expiry is earlear then Auth key life time start timestamp!!\n\n");
if ((unsigned long long)key_timestamp << 16 > token_timestamp + ((unsigned long long)token_lifetime << 16)) {
fprintf(stderr, "\nWARNING: Token expiry is earlear then Auth key life time start timestamp!!\n\n");
} else {
if( (unsigned long long)key_timestamp<<16 > token_timestamp) {
fprintf(stderr,"\nWARNING: Token life time start timestamp is earlier then Auth key start timestamp!!\n\n");
}
if ((unsigned long long)key_timestamp << 16 > token_timestamp) {
fprintf(stderr, "\nWARNING: Token life time start timestamp is earlier then Auth key start timestamp!!\n\n");
}
}
if( (unsigned long long)( key_timestamp + key_lifetime )<<16 < token_timestamp ) {
fprintf(stderr,"\nWARNING: Auth key will expire before token lifetime start timestamp!!\n\n");
if ((unsigned long long)(key_timestamp + key_lifetime) << 16 < token_timestamp) {
fprintf(stderr, "\nWARNING: Auth key will expire before token lifetime start timestamp!!\n\n");
} else {
if( (unsigned long long)( key_timestamp + key_lifetime)<<16 < token_timestamp + ((unsigned long long)token_lifetime << 16) ) {
fprintf(stderr,"\nWARNING: Auth key will expire before token expiry!!\n\n");
}
if ((unsigned long long)(key_timestamp + key_lifetime) << 16 <
token_timestamp + ((unsigned long long)token_lifetime << 16)) {
fprintf(stderr, "\nWARNING: Auth key will expire before token expiry!!\n\n");
}
}
if ( setup_ikm_key(kid, base64encoded_ltk, key_timestamp, key_lifetime, as_rs_alg, &key) == 0 ) {
if(encrypt_flag) {
if (encode_token(server_name, gcm_nonce, mac_key, token_timestamp, token_lifetime, key, base64encoded_etoken) == 0 ) {
printf("{\n");
printf(" \"access_token\":\"%s\",\n",base64encoded_etoken);
printf(" \"token_type\":\"pop\",\n");
printf(" \"expires_in\":%u,\n",token_lifetime);
printf(" \"kid\":\"%s\",\n",kid);
printf(" \"key\":\"%s\",\n",mac_key);
printf(" \"alg\":\"%s\"\n",hmac_alg);
printf("}\n");
} else {
fprintf(stderr, "Error during token encode\n");
exit(-1);
}
if (setup_ikm_key(kid, base64encoded_ltk, key_timestamp, key_lifetime, as_rs_alg, &key) == 0) {
if (encrypt_flag) {
if (encode_token(server_name, gcm_nonce, mac_key, token_timestamp, token_lifetime, key, base64encoded_etoken) ==
0) {
printf("{\n");
printf(" \"access_token\":\"%s\",\n", base64encoded_etoken);
printf(" \"token_type\":\"pop\",\n");
printf(" \"expires_in\":%u,\n", token_lifetime);
printf(" \"kid\":\"%s\",\n", kid);
printf(" \"key\":\"%s\",\n", mac_key);
printf(" \"alg\":\"%s\"\n", hmac_alg);
printf("}\n");
} else {
fprintf(stderr, "Error during token encode\n");
exit(-1);
}
if (decrypt_flag) {
oauth_token dot;
if ( validate_decode_token(server_name, key, base64encoded_etoken,&dot) == 0) {
printf("-=Valid token!=-\n");
if (verbose_flag) print_token_body(&dot);
} else {
fprintf(stderr, "Error during token validation and decoding\n");
exit(-1);
}
}
if (decrypt_flag) {
oauth_token dot;
if (validate_decode_token(server_name, key, base64encoded_etoken, &dot) == 0) {
printf("-=Valid token!=-\n");
if (verbose_flag)
print_token_body(&dot);
} else {
fprintf(stderr, "Error during token validation and decoding\n");
exit(-1);
}
} else {
fprintf(stderr, "Error during key setup\n");
exit(-1);
}
} else {
fprintf(stderr, "Error during key setup\n");
exit(-1);
}
}
return 0;

View File

@ -28,12 +28,12 @@
* SUCH DAMAGE.
*/
#include "apputils.h"
#include "ns_turn_utils.h"
#include "udpserver.h"
#include "apputils.h"
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#if defined(_MSC_VER)
@ -44,66 +44,62 @@
//////////////// local definitions /////////////////
static char Usage[] =
"Usage: server [options]\n"
"Options:\n"
" -p Listening UDP port (Default: 3480)\n"
" -d Listening interface device (optional)\n"
" -L Listening address\n"
" -v verbose\n";
static char Usage[] = "Usage: server [options]\n"
"Options:\n"
" -p Listening UDP port (Default: 3480)\n"
" -d Listening interface device (optional)\n"
" -L Listening address\n"
" -v verbose\n";
//////////////////////////////////////////////////
int main(int argc, char **argv)
{
int port = PEER_DEFAULT_PORT;
char **local_addr_list=NULL;
size_t las = 0;
int verbose = TURN_VERBOSE_NONE;
int c;
char ifname[1025] = "\0";
int main(int argc, char **argv) {
int port = PEER_DEFAULT_PORT;
char **local_addr_list = NULL;
size_t las = 0;
int verbose = TURN_VERBOSE_NONE;
int c;
char ifname[1025] = "\0";
if (socket_init()) return -1;
if (socket_init())
return -1;
IS_TURN_SERVER = 1;
IS_TURN_SERVER = 1;
set_logfile("stdout");
set_no_stdout_log(1);
set_system_parameters(0);
set_logfile("stdout");
set_no_stdout_log(1);
set_system_parameters(0);
while ((c = getopt(argc, argv, "d:p:L:v")) != -1)
switch (c){
case 'd':
STRCPY(ifname, optarg);
break;
case 'p':
port = atoi(optarg);
break;
case 'L':
local_addr_list = (char**)realloc(local_addr_list,++las*sizeof(char*));
local_addr_list[las-1]=strdup(optarg);
break;
case 'v':
verbose = TURN_VERBOSE_NORMAL;
break;
default:
fprintf(stderr, "%s\n", Usage);
exit(1);
}
while ((c = getopt(argc, argv, "d:p:L:v")) != -1)
switch (c) {
case 'd':
STRCPY(ifname, optarg);
break;
case 'p':
port = atoi(optarg);
break;
case 'L':
local_addr_list = (char **)realloc(local_addr_list, ++las * sizeof(char *));
local_addr_list[las - 1] = strdup(optarg);
break;
case 'v':
verbose = TURN_VERBOSE_NORMAL;
break;
default:
fprintf(stderr, "%s\n", Usage);
exit(1);
}
if(las<1) {
local_addr_list = (char**)realloc(local_addr_list,++las*sizeof(char*));
local_addr_list[las-1]=strdup("0.0.0.0");
local_addr_list = (char**)realloc(local_addr_list,++las*sizeof(char*));
local_addr_list[las-1]=strdup("::");
}
if (las < 1) {
local_addr_list = (char **)realloc(local_addr_list, ++las * sizeof(char *));
local_addr_list[las - 1] = strdup("0.0.0.0");
local_addr_list = (char **)realloc(local_addr_list, ++las * sizeof(char *));
local_addr_list[las - 1] = strdup("::");
}
server_type *server = start_udp_server(verbose, ifname, local_addr_list, las, port);
run_udp_server(server);
clean_udp_server(server);
server_type* server = start_udp_server(verbose, ifname, local_addr_list, las, port);
run_udp_server(server);
clean_udp_server(server);
return 0;
return 0;
}

View File

@ -28,17 +28,18 @@
* SUCH DAMAGE.
*/
#include "apputils.h"
#include "udpserver.h"
#include "apputils.h"
#include "stun_buffer.h"
/////////////// io handlers ///////////////////
static void udp_server_input_handler(evutil_socket_t fd, short what, void* arg) {
static void udp_server_input_handler(evutil_socket_t fd, short what, void *arg) {
if(!(what&EV_READ)) return;
if (!(what & EV_READ))
return;
ioa_addr *addr = (ioa_addr*)arg;
ioa_addr *addr = (ioa_addr *)arg;
int len = 0;
int slen = get_ioa_addr_len(addr);
@ -46,34 +47,36 @@ static void udp_server_input_handler(evutil_socket_t fd, short what, void* arg)
ioa_addr remote_addr;
do {
len = recvfrom(fd, buffer.buf, sizeof(buffer.buf)-1, 0, (struct sockaddr*) &remote_addr, (socklen_t*) &slen);
} while(len<0 && (errno==EINTR));
buffer.len=len;
len = recvfrom(fd, buffer.buf, sizeof(buffer.buf) - 1, 0, (struct sockaddr *)&remote_addr, (socklen_t *)&slen);
} while (len < 0 && (errno == EINTR));
if(len>=0) {
buffer.len = len;
if (len >= 0) {
do {
len = sendto(fd, buffer.buf, buffer.len, 0, (const struct sockaddr*) &remote_addr, (socklen_t) slen);
len = sendto(fd, buffer.buf, buffer.len, 0, (const struct sockaddr *)&remote_addr, (socklen_t)slen);
} while (len < 0 && ((errno == EINTR) || (errno == ENOBUFS) || (errno == EAGAIN)));
}
}
///////////////////// operations //////////////////////////
static int udp_create_server_socket(server_type* server,
const char* ifname, const char *local_address, int port) {
static int udp_create_server_socket(server_type *server, const char *ifname, const char *local_address, int port) {
if(server && server->verbose) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Start\n");
if (server && server->verbose)
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Start\n");
if(!server) return -1;
if (!server)
return -1;
evutil_socket_t udp_fd = -1;
ioa_addr *server_addr = (ioa_addr*)malloc(sizeof(ioa_addr));
ioa_addr *server_addr = (ioa_addr *)malloc(sizeof(ioa_addr));
STRCPY(server->ifname,ifname);
STRCPY(server->ifname, ifname);
if (make_ioa_addr((const uint8_t *)local_address, port, server_addr) < 0)
return -1;
if(make_ioa_addr((const uint8_t*)local_address, port, server_addr)<0) return -1;
udp_fd = socket(server_addr->ss.sa_family, RELAY_DGRAM_SOCKET_TYPE, RELAY_DGRAM_SOCKET_PROTOCOL);
if (udp_fd < 0) {
perror("socket");
@ -81,49 +84,53 @@ static int udp_create_server_socket(server_type* server,
return -1;
}
if(sock_bind_to_device(udp_fd, (unsigned char*)server->ifname)<0) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Cannot bind udp server socket to device %s\n",server->ifname);
if (sock_bind_to_device(udp_fd, (unsigned char *)server->ifname) < 0) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Cannot bind udp server socket to device %s\n", server->ifname);
}
set_sock_buf_size(udp_fd,UR_SERVER_SOCK_BUF_SIZE);
if(addr_bind(udp_fd,server_addr,1,1,UDP_SOCKET)<0) return -1;
set_sock_buf_size(udp_fd, UR_SERVER_SOCK_BUF_SIZE);
if (addr_bind(udp_fd, server_addr, 1, 1, UDP_SOCKET) < 0)
return -1;
socket_set_nonblocking(udp_fd);
struct event *udp_ev = event_new(server->event_base,udp_fd,EV_READ|EV_PERSIST,
udp_server_input_handler,server_addr);
event_add(udp_ev,NULL);
if(server && server->verbose) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "End\n");
struct event *udp_ev =
event_new(server->event_base, udp_fd, EV_READ | EV_PERSIST, udp_server_input_handler, server_addr);
event_add(udp_ev, NULL);
if (server && server->verbose)
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "End\n");
return 0;
}
static server_type* init_server(int verbose, const char* ifname, char **local_addresses, size_t las, int port) {
static server_type *init_server(int verbose, const char *ifname, char **local_addresses, size_t las, int port) {
server_type* server=(server_type*)malloc(sizeof(server_type));
server_type *server = (server_type *)malloc(sizeof(server_type));
if(!server) return server;
if (!server)
return server;
memset(server, 0, sizeof(server_type));
server->verbose=verbose;
server->verbose = verbose;
server->event_base = turn_event_base_new();
while(las) {
while (las) {
udp_create_server_socket(server, ifname, local_addresses[--las], port);
udp_create_server_socket(server, ifname, local_addresses[las], port+1);
udp_create_server_socket(server, ifname, local_addresses[las], port + 1);
}
return server;
}
static int clean_server(server_type* server) {
if(server) {
if(server->event_base) event_base_free(server->event_base);
static int clean_server(server_type *server) {
if (server) {
if (server->event_base)
event_base_free(server->event_base);
free(server);
}
return 0;
@ -131,14 +138,15 @@ static int clean_server(server_type* server) {
///////////////////////////////////////////////////////////
static void run_events(server_type* server) {
static void run_events(server_type *server) {
if(!server) return;
if (!server)
return;
struct timeval timeout;
timeout.tv_sec=0;
timeout.tv_usec=100000;
timeout.tv_sec = 0;
timeout.tv_usec = 100000;
event_base_loopexit(server->event_base, &timeout);
event_base_dispatch(server->event_base);
@ -146,28 +154,28 @@ static void run_events(server_type* server) {
/////////////////////////////////////////////////////////////
server_type* start_udp_server(int verbose, const char* ifname, char **local_addresses, size_t las, int port) {
server_type *start_udp_server(int verbose, const char *ifname, char **local_addresses, size_t las, int port) {
return init_server(verbose, ifname, local_addresses, las, port);
}
void run_udp_server(server_type* server) {
if(server) {
unsigned int cycle=0;
void run_udp_server(server_type *server) {
if (server) {
unsigned int cycle = 0;
while (1) {
cycle++;
run_events(server);
}
}
}
}
void clean_udp_server(server_type* server) {
if(server) clean_server(server);
void clean_udp_server(server_type *server) {
if (server)
clean_server(server);
}
//////////////////////////////////////////////////////////////////

View File

@ -50,17 +50,17 @@ typedef struct server_info server_type;
struct server_info {
char ifname[1025];
struct event_base* event_base;
struct event_base *event_base;
int verbose;
};
//////////////////////////////
server_type* start_udp_server(int verbose, const char* ifname, char **local_addresses, size_t las, int port);
server_type *start_udp_server(int verbose, const char *ifname, char **local_addresses, size_t las, int port);
void run_udp_server(server_type* server);
void run_udp_server(server_type *server);
void clean_udp_server(server_type* server);
void clean_udp_server(server_type *server);
///////////////////////////////////////////

View File

@ -12,81 +12,78 @@
#define GET_ACME_PREFIX_LEN 32
static int is_acme_req(char *req, size_t len) {
static const char *A = " - 0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ _ abcdefghijklmnopqrstuvwxyz ";
int c, i, k;
static const char *A = " - 0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ "
" _ abcdefghijklmnopqrstuvwxyz ";
int c, i, k;
// Check first request line. Should be like: GET path HTTP/1.x
if (strncmp(req, GET_ACME_PREFIX, GET_ACME_PREFIX_LEN))
return -1;
// Usually (for LE) the "method path" is 32 + 43 = 55 chars. But other
// implementations may choose longer pathes. We define PATHMAX = 127 chars
// to be prepared for "DoS" attacks (STUN msg size max. is ~ 64K).
len -= 21; // min size of trailing headers
if (len > 131)
len = 131;
for (i=GET_ACME_PREFIX_LEN; i < (int) len; i++) {
// find the end of the path
if (req[i] != ' ')
continue;
// consider path < 10 chars invalid. Also we wanna see a "trailer".
if (i < (GET_ACME_PREFIX_LEN + 10) || strncmp(req + i, " HTTP/1.", 8))
return -2;
// finally check for allowed chars
for (k=GET_ACME_PREFIX_LEN; k < i; k++) {
c = req[k];
if ((c > 127) || (A[c] == ' '))
return -3;
}
// all checks passed: sufficient for us to answer with a redirect
return i;
}
return -4; // end of path not found
// Check first request line. Should be like: GET path HTTP/1.x
if (strncmp(req, GET_ACME_PREFIX, GET_ACME_PREFIX_LEN))
return -1;
// Usually (for LE) the "method path" is 32 + 43 = 55 chars. But other
// implementations may choose longer pathes. We define PATHMAX = 127 chars
// to be prepared for "DoS" attacks (STUN msg size max. is ~ 64K).
len -= 21; // min size of trailing headers
if (len > 131)
len = 131;
for (i = GET_ACME_PREFIX_LEN; i < (int)len; i++) {
// find the end of the path
if (req[i] != ' ')
continue;
// consider path < 10 chars invalid. Also we wanna see a "trailer".
if (i < (GET_ACME_PREFIX_LEN + 10) || strncmp(req + i, " HTTP/1.", 8))
return -2;
// finally check for allowed chars
for (k = GET_ACME_PREFIX_LEN; k < i; k++) {
c = req[k];
if ((c > 127) || (A[c] == ' '))
return -3;
}
// all checks passed: sufficient for us to answer with a redirect
return i;
}
return -4; // end of path not found
}
int try_acme_redirect(char *req, size_t len, const char *url,
ioa_socket_handle s)
{
static const char *HTML =
"<html><head><title>301 Moved Permanently</title></head>\
int try_acme_redirect(char *req, size_t len, const char *url, ioa_socket_handle s) {
static const char *HTML = "<html><head><title>301 Moved Permanently</title></head>\
<body><h1>301 Moved Permanently</h1></body></html>";
char http_response[1024];
size_t plen, rlen;
char http_response[1024];
size_t plen, rlen;
if (url == NULL || url[0] == '\0' || req == NULL || s == 0 )
return 1;
if (len < (GET_ACME_PREFIX_LEN + 32) || len > (512 - GET_ACME_PREFIX_LEN)
|| (plen = is_acme_req(req, len)) < (GET_ACME_PREFIX_LEN + 1))
return 2;
if (url == NULL || url[0] == '\0' || req == NULL || s == 0)
return 1;
if (len < (GET_ACME_PREFIX_LEN + 32) || len > (512 - GET_ACME_PREFIX_LEN) ||
(plen = is_acme_req(req, len)) < (GET_ACME_PREFIX_LEN + 1))
return 2;
req[plen] = '\0';
req[plen] = '\0';
snprintf(http_response, sizeof(http_response) - 1,
"HTTP/1.1 301 Moved Permanently\r\n"
"Content-Type: text/html\r\n"
"Content-Length: %zu\r\n"
"Connection: close\r\n"
"Location: %s%s\r\n"
"\r\n%s", strlen(HTML), url, req + GET_ACME_PREFIX_LEN, HTML);
snprintf(http_response, sizeof(http_response) - 1,
"HTTP/1.1 301 Moved Permanently\r\n"
"Content-Type: text/html\r\n"
"Content-Length: %zu\r\n"
"Connection: close\r\n"
"Location: %s%s\r\n"
"\r\n%s",
strlen(HTML), url, req + GET_ACME_PREFIX_LEN, HTML);
rlen = strlen(http_response);
rlen = strlen(http_response);
#ifdef LIBEV_OK
ioa_network_buffer_handle nbh_acme = ioa_network_buffer_allocate(s->e);
uint8_t *data = ioa_network_buffer_data(nbh_acme);
memcpy(data, http_response, rlen);
ioa_network_buffer_set_size(nbh_acme, rlen);
send_data_from_ioa_socket_nbh(s, NULL, nbh_acme, TTL_IGNORE, TOS_IGNORE, NULL);
ioa_network_buffer_handle nbh_acme = ioa_network_buffer_allocate(s->e);
uint8_t *data = ioa_network_buffer_data(nbh_acme);
memcpy(data, http_response, rlen);
ioa_network_buffer_set_size(nbh_acme, rlen);
send_data_from_ioa_socket_nbh(s, NULL, nbh_acme, TTL_IGNORE, TOS_IGNORE, NULL);
#else
if (write(s->fd, http_response, rlen) == -1) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING,
"Sending redirect to '%s%s' failed",url, req + GET_ACME_PREFIX_LEN);
} else if (((turn_turnserver *)s->session->server)->verbose) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "ACME redirected to %s%s\n",
url, req + GET_ACME_PREFIX_LEN);
}
if (write(s->fd, http_response, rlen) == -1) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "Sending redirect to '%s%s' failed", url, req + GET_ACME_PREFIX_LEN);
} else if (((turn_turnserver *)s->session->server)->verbose) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "ACME redirected to %s%s\n", url, req + GET_ACME_PREFIX_LEN);
}
#endif
req[plen] = ' ';
req[plen] = ' ';
return 0;
return 0;
}

View File

@ -31,12 +31,12 @@
#ifndef __TURN_ACME__
#define __TURN_ACME__
#include "ns_turn_utils.h"
#include "ns_turn_server.h"
#include "apputils.h"
#include "ns_turn_server.h"
#include "ns_turn_utils.h"
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
@ -54,4 +54,3 @@ int try_acme_redirect(char *req, size_t len, const char *url, ioa_socket_handle
#endif
/// __TURN_ACME__ ///

File diff suppressed because it is too large Load Diff

View File

@ -38,7 +38,7 @@
extern "C" {
#endif
const turn_dbdriver_t * get_mongo_dbdriver(void);
const turn_dbdriver_t *get_mongo_dbdriver(void);
#ifdef __cplusplus
}
@ -46,4 +46,3 @@ const turn_dbdriver_t * get_mongo_dbdriver(void);
#endif
/// __DBD_MONGODB__///

File diff suppressed because it is too large Load Diff

View File

@ -38,7 +38,7 @@
extern "C" {
#endif
const turn_dbdriver_t * get_mysql_dbdriver(void);
const turn_dbdriver_t *get_mysql_dbdriver(void);
#ifdef __cplusplus
}
@ -46,4 +46,3 @@ const turn_dbdriver_t * get_mysql_dbdriver(void);
#endif
/// __DBD_MYSQL__///

File diff suppressed because it is too large Load Diff

View File

@ -38,7 +38,7 @@
extern "C" {
#endif
const turn_dbdriver_t * get_pgsql_dbdriver(void);
const turn_dbdriver_t *get_pgsql_dbdriver(void);
#ifdef __cplusplus
}
@ -46,4 +46,3 @@ const turn_dbdriver_t * get_pgsql_dbdriver(void);
#endif
/// __DBD_POSTGRESQL__///

File diff suppressed because it is too large Load Diff

View File

@ -39,8 +39,9 @@
extern "C" {
#endif
const turn_dbdriver_t * get_redis_dbdriver(void);
redis_context_handle get_redis_async_connection(struct event_base *base, redis_stats_db_t* connection_string, int delete_keys);
const turn_dbdriver_t *get_redis_dbdriver(void);
redis_context_handle get_redis_async_connection(struct event_base *base, redis_stats_db_t *connection_string,
int delete_keys);
#ifdef __cplusplus
}
@ -48,4 +49,3 @@ redis_context_handle get_redis_async_connection(struct event_base *base, redis_s
#endif
/// __DBD_REDIS__///

File diff suppressed because it is too large Load Diff

View File

@ -38,7 +38,7 @@
extern "C" {
#endif
const turn_dbdriver_t * get_sqlite_dbdriver(void);
const turn_dbdriver_t *get_sqlite_dbdriver(void);
#ifdef __cplusplus
}
@ -46,4 +46,3 @@ const turn_dbdriver_t * get_sqlite_dbdriver(void);
#endif
/// __DBD_SQLITE__///

View File

@ -33,115 +33,102 @@
#include "apputils.h"
#include "dbdriver.h"
#include "dbd_sqlite.h"
#include "dbd_pgsql.h"
#include "dbd_mysql.h"
#include "dbd_mongo.h"
#include "dbd_mysql.h"
#include "dbd_pgsql.h"
#include "dbd_redis.h"
#include "dbd_sqlite.h"
#include "dbdriver.h"
static void make_connection_key(void)
{
(void) pthread_key_create(&connection_key, NULL);
}
static void make_connection_key(void) { (void)pthread_key_create(&connection_key, NULL); }
pthread_key_t connection_key;
pthread_once_t connection_key_once = PTHREAD_ONCE_INIT;
int convert_string_key_to_binary(char* keysource, hmackey_t key, size_t sz) {
char is[3];
size_t i;
unsigned int v;
is[2]=0;
for(i=0;i<sz;i++) {
is[0]=keysource[i*2];
is[1]=keysource[i*2+1];
sscanf(is,"%02x",&v);
key[i]=(unsigned char)v;
}
return 0;
int convert_string_key_to_binary(char *keysource, hmackey_t key, size_t sz) {
char is[3];
size_t i;
unsigned int v;
is[2] = 0;
for (i = 0; i < sz; i++) {
is[0] = keysource[i * 2];
is[1] = keysource[i * 2 + 1];
sscanf(is, "%02x", &v);
key[i] = (unsigned char)v;
}
return 0;
}
persistent_users_db_t * get_persistent_users_db(void) {
return &(turn_params.default_users_db.persistent_users_db);
}
persistent_users_db_t *get_persistent_users_db(void) { return &(turn_params.default_users_db.persistent_users_db); }
const turn_dbdriver_t * get_dbdriver(void)
{
if (turn_params.default_users_db.userdb_type == TURN_USERDB_TYPE_UNKNOWN)
return NULL;
const turn_dbdriver_t *get_dbdriver(void) {
if (turn_params.default_users_db.userdb_type == TURN_USERDB_TYPE_UNKNOWN)
return NULL;
(void) pthread_once(&connection_key_once, make_connection_key);
(void)pthread_once(&connection_key_once, make_connection_key);
static const turn_dbdriver_t * _driver = NULL;
static const turn_dbdriver_t *_driver = NULL;
if (_driver == NULL) {
if (_driver == NULL) {
switch (turn_params.default_users_db.userdb_type){
switch (turn_params.default_users_db.userdb_type) {
#if !defined(TURN_NO_SQLITE)
case TURN_USERDB_TYPE_SQLITE:
_driver = get_sqlite_dbdriver();
break;
case TURN_USERDB_TYPE_SQLITE:
_driver = get_sqlite_dbdriver();
break;
#endif
#if !defined(TURN_NO_PQ)
case TURN_USERDB_TYPE_PQ:
_driver = get_pgsql_dbdriver();
break;
case TURN_USERDB_TYPE_PQ:
_driver = get_pgsql_dbdriver();
break;
#endif
#if !defined(TURN_NO_MYSQL)
case TURN_USERDB_TYPE_MYSQL:
_driver = get_mysql_dbdriver();
break;
case TURN_USERDB_TYPE_MYSQL:
_driver = get_mysql_dbdriver();
break;
#endif
#if !defined(TURN_NO_MONGO)
case TURN_USERDB_TYPE_MONGO:
_driver = get_mongo_dbdriver();
break;
case TURN_USERDB_TYPE_MONGO:
_driver = get_mongo_dbdriver();
break;
#endif
case TURN_USERDB_TYPE_REDIS:
_driver = get_redis_dbdriver();
break;
default:
break;
}
}
return _driver;
case TURN_USERDB_TYPE_REDIS:
_driver = get_redis_dbdriver();
break;
default:
break;
}
}
return _driver;
}
char* sanitize_userdb_string(char* udb) {
char * ret = NULL;
char * pstart;
char * pend;
char *sanitize_userdb_string(char *udb) {
char *ret = NULL;
char *pstart;
char *pend;
/* host=localhost dbname=coturn user=turn password=turn connect_timeout=30 */
ret = strdup(udb);
pstart = strstr (ret,"password=");
if (pstart != NULL)
{
pstart += strlen("password=");
pend = strstr (pstart," ");
/* host=localhost dbname=coturn user=turn password=turn connect_timeout=30 */
ret = strdup(udb);
pstart = strstr(ret, "password=");
if (pstart != NULL) {
pstart += strlen("password=");
pend = strstr(pstart, " ");
size_t plen = pend - pstart;
if (pend == NULL) {
plen = strlen(pstart);
}
memset(pstart, '*', plen);
} else {
/* postgresql://username:password@/databasename */
pstart = strstr(ret, "postgresql://");
if (pstart != NULL) {
pstart += strlen("postgresql://");
pend = strstr(pstart, "@");
if (pend != NULL) {
size_t plen = pend - pstart;
if (pend == NULL)
{
plen = strlen(pstart);
}
memset(pstart,'*',plen);
memset(pstart, '*', plen);
}
}
else
{
/* postgresql://username:password@/databasename */
pstart = strstr (ret,"postgresql://");
if (pstart != NULL)
{
pstart += strlen("postgresql://");
pend = strstr (pstart,"@");
if (pend != NULL)
{
size_t plen = pend - pstart;
memset(pstart,'*',plen);
}
}
}
return ret;
}
return ret;
}

View File

@ -59,16 +59,17 @@ typedef struct _turn_dbdriver_t {
int (*add_origin)(uint8_t *origin, uint8_t *realm);
int (*del_origin)(uint8_t *origin);
int (*list_origins)(uint8_t *realm, secrets_list_t *origins, secrets_list_t *realms);
int (*set_realm_option_one)(uint8_t *realm, unsigned long value, const char* opt);
int (*set_realm_option_one)(uint8_t *realm, unsigned long value, const char *opt);
int (*list_realm_options)(uint8_t *realm);
void (*auth_ping)(void * rch);
int (*get_ip_list)(const char *kind, ip_range_list_t * list);
int (*set_permission_ip)(const char *kind, uint8_t *realm, const char* ip, int del);
void (*reread_realms)(secrets_list_t * realms_list);
void (*auth_ping)(void *rch);
int (*get_ip_list)(const char *kind, ip_range_list_t *list);
int (*set_permission_ip)(const char *kind, uint8_t *realm, const char *ip, int del);
void (*reread_realms)(secrets_list_t *realms_list);
int (*set_oauth_key)(oauth_key_data_raw *key);
int (*get_oauth_key)(const uint8_t *kid, oauth_key_data_raw *key);
int (*del_oauth_key)(const uint8_t *kid);
int (*list_oauth_keys)(secrets_list_t *kids,secrets_list_t *teas,secrets_list_t *tss,secrets_list_t *lts,secrets_list_t *realms);
int (*list_oauth_keys)(secrets_list_t *kids, secrets_list_t *teas, secrets_list_t *tss, secrets_list_t *lts,
secrets_list_t *realms);
int (*get_admin_user)(const uint8_t *usname, uint8_t *realm, password_t pwd);
int (*set_admin_user)(const uint8_t *usname, const uint8_t *realm, const password_t pwd);
int (*del_admin_user)(const uint8_t *usname);
@ -78,10 +79,10 @@ typedef struct _turn_dbdriver_t {
/////////// USER DB CHECK //////////////////
int convert_string_key_to_binary(char* keysource, hmackey_t key, size_t sz);
persistent_users_db_t * get_persistent_users_db(void);
const turn_dbdriver_t * get_dbdriver(void);
char* sanitize_userdb_string(char* udb);
int convert_string_key_to_binary(char *keysource, hmackey_t key, size_t sz);
persistent_users_db_t *get_persistent_users_db(void);
const turn_dbdriver_t *get_dbdriver(void);
char *sanitize_userdb_string(char *udb);
////////////////////////////////////////////
@ -91,4 +92,3 @@ char* sanitize_userdb_string(char* udb);
#endif
/// __DBDRIVER__///

File diff suppressed because it is too large Load Diff

View File

@ -54,18 +54,14 @@ typedef struct dtls_listener_relay_server_info dtls_listener_relay_server_type;
void setup_dtls_callbacks(SSL_CTX *ctx);
#endif
dtls_listener_relay_server_type* create_dtls_listener_server(const char* ifname,
const char *local_address,
int port,
int verbose,
ioa_engine_handle e,
turn_turnserver *ts,
int report_creation,
ioa_engine_new_connection_event_handler send_socket);
dtls_listener_relay_server_type *create_dtls_listener_server(const char *ifname, const char *local_address, int port,
int verbose, ioa_engine_handle e, turn_turnserver *ts,
int report_creation,
ioa_engine_new_connection_event_handler send_socket);
void udp_send_message(dtls_listener_relay_server_type *server, ioa_network_buffer_handle nbh, ioa_addr *dest);
ioa_engine_handle get_engine(dtls_listener_relay_server_type* server);
ioa_engine_handle get_engine(dtls_listener_relay_server_type *server);
///////////////////////////////////////////

View File

@ -40,344 +40,341 @@
//////////////////////////////////////
struct headers_list {
size_t n;
char **keys;
char **values;
size_t n;
char **keys;
char **values;
};
struct http_headers {
struct evkeyvalq *uri_headers;
struct headers_list *post_headers;
struct evkeyvalq *uri_headers;
struct headers_list *post_headers;
};
//////////////////////////////////////
static void write_http_echo(ioa_socket_handle s)
{
if(s && !ioa_socket_tobeclosed(s)) {
SOCKET_APP_TYPE sat = get_ioa_socket_app_type(s);
if((sat == HTTP_CLIENT_SOCKET) || (sat == HTTPS_CLIENT_SOCKET)) {
ioa_network_buffer_handle nbh_http = ioa_network_buffer_allocate(s->e);
size_t len_http = ioa_network_buffer_get_size(nbh_http);
uint8_t *data = ioa_network_buffer_data(nbh_http);
char data_http[1025];
char content_http[1025];
const char* title = "TURN Server";
snprintf(content_http,sizeof(content_http)-1,"<!DOCTYPE html>\r\n<html>\r\n <head>\r\n <title>%s</title>\r\n </head>\r\n <body>\r\n <b>%s</b> <br> <b><i>use https connection for the admin session</i></b>\r\n </body>\r\n</html>\r\n",title,title);
snprintf(data_http,sizeof(data_http)-1,"HTTP/1.0 200 OK\r\nServer: %s\r\nContent-Type: text/html; charset=UTF-8\r\nContent-Length: %d\r\n\r\n%.906s",TURN_SOFTWARE,(int)strlen(content_http),content_http);
len_http = strlen(data_http);
memcpy(data,data_http,len_http);
ioa_network_buffer_set_size(nbh_http,len_http);
send_data_from_ioa_socket_nbh(s, NULL, nbh_http, TTL_IGNORE, TOS_IGNORE,NULL);
}
}
static void write_http_echo(ioa_socket_handle s) {
if (s && !ioa_socket_tobeclosed(s)) {
SOCKET_APP_TYPE sat = get_ioa_socket_app_type(s);
if ((sat == HTTP_CLIENT_SOCKET) || (sat == HTTPS_CLIENT_SOCKET)) {
ioa_network_buffer_handle nbh_http = ioa_network_buffer_allocate(s->e);
size_t len_http = ioa_network_buffer_get_size(nbh_http);
uint8_t *data = ioa_network_buffer_data(nbh_http);
char data_http[1025];
char content_http[1025];
const char *title = "TURN Server";
snprintf(content_http, sizeof(content_http) - 1,
"<!DOCTYPE html>\r\n<html>\r\n <head>\r\n <title>%s</title>\r\n </head>\r\n <body>\r\n "
"<b>%s</b> <br> <b><i>use https connection for the admin session</i></b>\r\n </body>\r\n</html>\r\n",
title, title);
snprintf(
data_http, sizeof(data_http) - 1,
"HTTP/1.0 200 OK\r\nServer: %s\r\nContent-Type: text/html; charset=UTF-8\r\nContent-Length: %d\r\n\r\n%.906s",
TURN_SOFTWARE, (int)strlen(content_http), content_http);
len_http = strlen(data_http);
memcpy(data, data_http, len_http);
ioa_network_buffer_set_size(nbh_http, len_http);
send_data_from_ioa_socket_nbh(s, NULL, nbh_http, TTL_IGNORE, TOS_IGNORE, NULL);
}
}
}
void handle_http_echo(ioa_socket_handle s) {
write_http_echo(s);
}
void handle_http_echo(ioa_socket_handle s) { write_http_echo(s); }
const char* get_http_date_header(void)
{
static char buffer_date[256];
static char buffer_header[1025];
static const char* wds[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
static const char* mons[]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
const char *get_http_date_header(void) {
static char buffer_date[256];
static char buffer_header[1025];
static const char *wds[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
static const char *mons[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
time_t now = time(NULL);
struct tm *gmtm = gmtime(&now);
time_t now = time(NULL);
struct tm *gmtm = gmtime(&now);
buffer_header[0]=0;
buffer_date[0]=0;
if(gmtm) {
snprintf(buffer_date,sizeof(buffer_date)-1,"%s, %d %s %d %d:%d:%d GMT",wds[gmtm->tm_wday], gmtm->tm_mday, mons[gmtm->tm_mon], gmtm->tm_year+1900, gmtm->tm_hour, gmtm->tm_min, gmtm->tm_sec);
buffer_date[sizeof(buffer_date)-1]=0;
snprintf(buffer_header,sizeof(buffer_header)-1,"Date: %s\r\n",buffer_date);
buffer_header[sizeof(buffer_header)-1]=0;
}
buffer_header[0] = 0;
buffer_date[0] = 0;
if (gmtm) {
snprintf(buffer_date, sizeof(buffer_date) - 1, "%s, %d %s %d %d:%d:%d GMT", wds[gmtm->tm_wday], gmtm->tm_mday,
mons[gmtm->tm_mon], gmtm->tm_year + 1900, gmtm->tm_hour, gmtm->tm_min, gmtm->tm_sec);
buffer_date[sizeof(buffer_date) - 1] = 0;
snprintf(buffer_header, sizeof(buffer_header) - 1, "Date: %s\r\n", buffer_date);
buffer_header[sizeof(buffer_header) - 1] = 0;
}
return buffer_header;
return buffer_header;
}
///////////////////////////////////////////////
static struct headers_list * post_parse(char *data, size_t data_len)
{
while((*data=='\r')||(*data=='\n')) { ++data; --data_len; }
if (data_len) {
char *post_data = (char*)calloc(data_len + 1, sizeof(char));
if (post_data != NULL) {
memcpy(post_data, data, data_len);
char *fmarker = NULL;
char *fsplit = strtok_r(post_data, "&", &fmarker);
struct headers_list *list = (struct headers_list*)calloc(sizeof(struct headers_list), 1);
while (fsplit != NULL) {
char *vmarker = NULL;
char *key = strtok_r(fsplit, "=", &vmarker);
if (key == NULL)
break;
else {
char *value = strtok_r(NULL, "=", &vmarker);
char empty[1];
empty[0]=0;
value = value ? value : empty;
value = evhttp_decode_uri(value);
char *p = value;
while (*p) {
if (*p == '+')
*p = ' ';
p++;
}
list->keys = (char**)realloc(list->keys,sizeof(char*)*(list->n+1));
list->keys[list->n] = strdup(key);
list->values = (char**)realloc(list->values,sizeof(char*)*(list->n+1));
list->values[list->n] = value;
++(list->n);
fsplit = strtok_r(NULL, "&", &fmarker);
}
}
free(post_data);
return list;
}
}
return NULL;
static struct headers_list *post_parse(char *data, size_t data_len) {
while ((*data == '\r') || (*data == '\n')) {
++data;
--data_len;
}
if (data_len) {
char *post_data = (char *)calloc(data_len + 1, sizeof(char));
if (post_data != NULL) {
memcpy(post_data, data, data_len);
char *fmarker = NULL;
char *fsplit = strtok_r(post_data, "&", &fmarker);
struct headers_list *list = (struct headers_list *)calloc(sizeof(struct headers_list), 1);
while (fsplit != NULL) {
char *vmarker = NULL;
char *key = strtok_r(fsplit, "=", &vmarker);
if (key == NULL)
break;
else {
char *value = strtok_r(NULL, "=", &vmarker);
char empty[1];
empty[0] = 0;
value = value ? value : empty;
value = evhttp_decode_uri(value);
char *p = value;
while (*p) {
if (*p == '+')
*p = ' ';
p++;
}
list->keys = (char **)realloc(list->keys, sizeof(char *) * (list->n + 1));
list->keys[list->n] = strdup(key);
list->values = (char **)realloc(list->values, sizeof(char *) * (list->n + 1));
list->values[list->n] = value;
++(list->n);
fsplit = strtok_r(NULL, "&", &fmarker);
}
}
free(post_data);
return list;
}
}
return NULL;
}
static struct http_request* parse_http_request_1(struct http_request* ret, char* request, int parse_post)
{
static struct http_request *parse_http_request_1(struct http_request *ret, char *request, int parse_post) {
if(ret && request) {
if (ret && request) {
char* s = strstr(request," HTTP/");
if(!s) {
free(ret);
ret = NULL;
} else {
*s = 0;
char *s = strstr(request, " HTTP/");
if (!s) {
free(ret);
ret = NULL;
} else {
*s = 0;
struct evhttp_uri *uri = evhttp_uri_parse(request);
if(!uri) {
free(ret);
ret = NULL;
} else {
struct evhttp_uri *uri = evhttp_uri_parse(request);
if (!uri) {
free(ret);
ret = NULL;
} else {
const char *query = evhttp_uri_get_query(uri);
if(query) {
struct evkeyvalq* kv = (struct evkeyvalq*)calloc(sizeof(struct evkeyvalq), 1);
if(evhttp_parse_query_str(query, kv)<0) {
free(ret);
ret = NULL;
} else {
ret->headers = (struct http_headers*)calloc(sizeof(struct http_headers), 1);
ret->headers->uri_headers = kv;
}
}
const char *query = evhttp_uri_get_query(uri);
if (query) {
struct evkeyvalq *kv = (struct evkeyvalq *)calloc(sizeof(struct evkeyvalq), 1);
if (evhttp_parse_query_str(query, kv) < 0) {
free(ret);
ret = NULL;
} else {
ret->headers = (struct http_headers *)calloc(sizeof(struct http_headers), 1);
ret->headers->uri_headers = kv;
}
}
const char *path = evhttp_uri_get_path(uri);
if(path && ret)
ret->path = strdup(path);
const char *path = evhttp_uri_get_path(uri);
if (path && ret)
ret->path = strdup(path);
evhttp_uri_free(uri);
evhttp_uri_free(uri);
if(parse_post && ret) {
char *body = strstr(s+1,"\r\n\r\n");
if(body && body[0]) {
if(!ret->headers) {
ret->headers = (struct http_headers*)calloc(sizeof(struct http_headers), 1);
}
ret->headers->post_headers = post_parse(body,strlen(body));
}
}
}
if (parse_post && ret) {
char *body = strstr(s + 1, "\r\n\r\n");
if (body && body[0]) {
if (!ret->headers) {
ret->headers = (struct http_headers *)calloc(sizeof(struct http_headers), 1);
}
ret->headers->post_headers = post_parse(body, strlen(body));
}
}
}
*s = ' ';
}
}
*s = ' ';
}
}
return ret;
return ret;
}
struct http_request* parse_http_request(char* request) {
struct http_request *parse_http_request(char *request) {
struct http_request* ret = NULL;
struct http_request *ret = NULL;
if(request) {
if (request) {
ret = (struct http_request*)calloc(sizeof(struct http_request), 1);
ret = (struct http_request *)calloc(sizeof(struct http_request), 1);
if(strstr(request,"GET ") == request) {
ret->rtype = HRT_GET;
ret = parse_http_request_1(ret,request+4,0);
} else if(strstr(request,"HEAD ") == request) {
ret->rtype = HRT_HEAD;
ret = parse_http_request_1(ret,request+5,0);
} else if(strstr(request,"POST ") == request) {
ret->rtype = HRT_POST;
ret = parse_http_request_1(ret,request+5,1);
} else if(strstr(request,"PUT ") == request) {
ret->rtype = HRT_PUT;
ret = parse_http_request_1(ret,request+4,1);
} else if(strstr(request,"DELETE ") == request) {
ret->rtype = HRT_DELETE;
ret = parse_http_request_1(ret,request+7,1);
} else {
free(ret);
ret = NULL;
}
}
if (strstr(request, "GET ") == request) {
ret->rtype = HRT_GET;
ret = parse_http_request_1(ret, request + 4, 0);
} else if (strstr(request, "HEAD ") == request) {
ret->rtype = HRT_HEAD;
ret = parse_http_request_1(ret, request + 5, 0);
} else if (strstr(request, "POST ") == request) {
ret->rtype = HRT_POST;
ret = parse_http_request_1(ret, request + 5, 1);
} else if (strstr(request, "PUT ") == request) {
ret->rtype = HRT_PUT;
ret = parse_http_request_1(ret, request + 4, 1);
} else if (strstr(request, "DELETE ") == request) {
ret->rtype = HRT_DELETE;
ret = parse_http_request_1(ret, request + 7, 1);
} else {
free(ret);
ret = NULL;
}
}
return ret;
return ret;
}
static const char * get_headers_list_value(struct headers_list *h, const char* key) {
const char* ret = NULL;
if(h && h->keys && h->values && key && key[0]) {
size_t i = 0;
for(i=0;i<h->n;++i) {
if(h->keys[i] && !strcmp(key,h->keys[i]) && h->values[i]) {
ret = h->values[i];
break;
}
}
}
return ret;
static const char *get_headers_list_value(struct headers_list *h, const char *key) {
const char *ret = NULL;
if (h && h->keys && h->values && key && key[0]) {
size_t i = 0;
for (i = 0; i < h->n; ++i) {
if (h->keys[i] && !strcmp(key, h->keys[i]) && h->values[i]) {
ret = h->values[i];
break;
}
}
}
return ret;
}
static void free_headers_list(struct headers_list *h) {
if(h) {
if(h->keys) {
size_t i = 0;
for(i=0;i<h->n;++i) {
if(h->keys[i]) {
free(h->keys[i]);
h->keys[i]=NULL;
}
}
free(h->keys);
h->keys = NULL;
}
if(h->values) {
size_t i = 0;
for(i=0;i<h->n;++i) {
if(h->values[i]) {
free(h->values[i]);
h->values[i]=NULL;
}
}
free(h->values);
h->values = NULL;
}
h->n = 0;
free(h);
}
if (h) {
if (h->keys) {
size_t i = 0;
for (i = 0; i < h->n; ++i) {
if (h->keys[i]) {
free(h->keys[i]);
h->keys[i] = NULL;
}
}
free(h->keys);
h->keys = NULL;
}
if (h->values) {
size_t i = 0;
for (i = 0; i < h->n; ++i) {
if (h->values[i]) {
free(h->values[i]);
h->values[i] = NULL;
}
}
free(h->values);
h->values = NULL;
}
h->n = 0;
free(h);
}
}
const char *get_http_header_value(const struct http_request *request, const char* key, const char* default_value) {
const char *ret = NULL;
if(key && key[0] && request && request->headers) {
if(request->headers->uri_headers) {
ret = evhttp_find_header(request->headers->uri_headers,key);
}
if(!ret && request->headers->post_headers) {
ret = get_headers_list_value(request->headers->post_headers,key);
}
}
if(!ret) {
ret = default_value;
}
return ret;
const char *get_http_header_value(const struct http_request *request, const char *key, const char *default_value) {
const char *ret = NULL;
if (key && key[0] && request && request->headers) {
if (request->headers->uri_headers) {
ret = evhttp_find_header(request->headers->uri_headers, key);
}
if (!ret && request->headers->post_headers) {
ret = get_headers_list_value(request->headers->post_headers, key);
}
}
if (!ret) {
ret = default_value;
}
return ret;
}
void free_http_request(struct http_request *request) {
if(request) {
if(request->path) {
free(request->path);
request->path = NULL;
}
if(request->headers) {
if(request->headers->uri_headers) {
evhttp_clear_headers(request->headers->uri_headers);
free(request->headers->uri_headers);
request->headers->uri_headers = NULL;
}
if(request->headers->post_headers) {
free_headers_list(request->headers->post_headers);
request->headers->post_headers = NULL;
}
free(request->headers);
request->headers = NULL;
}
free(request);
}
if (request) {
if (request->path) {
free(request->path);
request->path = NULL;
}
if (request->headers) {
if (request->headers->uri_headers) {
evhttp_clear_headers(request->headers->uri_headers);
free(request->headers->uri_headers);
request->headers->uri_headers = NULL;
}
if (request->headers->post_headers) {
free_headers_list(request->headers->post_headers);
request->headers->post_headers = NULL;
}
free(request->headers);
request->headers = NULL;
}
free(request);
}
}
////////////////////////////////////////////
struct str_buffer {
size_t capacity;
size_t sz;
char* buffer;
size_t capacity;
size_t sz;
char *buffer;
};
struct str_buffer* str_buffer_new(void)
{
struct str_buffer* ret = (struct str_buffer*)calloc(sizeof(struct str_buffer), 1);
struct str_buffer *str_buffer_new(void) {
struct str_buffer *ret = (struct str_buffer *)calloc(sizeof(struct str_buffer), 1);
ret->buffer = (char*)malloc(1);
ret->buffer[0] = 0;
ret->capacity = 1;
return ret;
ret->buffer = (char *)malloc(1);
ret->buffer[0] = 0;
ret->capacity = 1;
return ret;
}
void str_buffer_append(struct str_buffer* sb, const char* str)
{
if(sb && str && str[0]) {
size_t len = strlen(str);
while(sb->sz + len + 1 > sb->capacity) {
sb->capacity += len + 1024;
sb->buffer = (char*)realloc(sb->buffer,sb->capacity);
}
memcpy(sb->buffer+sb->sz,str,len+1);
sb->sz += len;
}
void str_buffer_append(struct str_buffer *sb, const char *str) {
if (sb && str && str[0]) {
size_t len = strlen(str);
while (sb->sz + len + 1 > sb->capacity) {
sb->capacity += len + 1024;
sb->buffer = (char *)realloc(sb->buffer, sb->capacity);
}
memcpy(sb->buffer + sb->sz, str, len + 1);
sb->sz += len;
}
}
void str_buffer_append_sz(struct str_buffer* sb, size_t sz)
{
char ssz[129];
snprintf(ssz,sizeof(ssz)-1,"%lu",(unsigned long)sz);
str_buffer_append(sb,ssz);
void str_buffer_append_sz(struct str_buffer *sb, size_t sz) {
char ssz[129];
snprintf(ssz, sizeof(ssz) - 1, "%lu", (unsigned long)sz);
str_buffer_append(sb, ssz);
}
void str_buffer_append_sid(struct str_buffer* sb, turnsession_id sid)
{
char ssz[129];
snprintf(ssz,sizeof(ssz)-1,"%018llu",(unsigned long long)sid);
str_buffer_append(sb,ssz);
void str_buffer_append_sid(struct str_buffer *sb, turnsession_id sid) {
char ssz[129];
snprintf(ssz, sizeof(ssz) - 1, "%018llu", (unsigned long long)sid);
str_buffer_append(sb, ssz);
}
const char* str_buffer_get_str(const struct str_buffer *sb)
{
if(sb) {
return sb->buffer;
}
return NULL;
const char *str_buffer_get_str(const struct str_buffer *sb) {
if (sb) {
return sb->buffer;
}
return NULL;
}
size_t str_buffer_get_str_len(const struct str_buffer *sb)
{
if(sb) {
return sb->sz;
}
return 0;
size_t str_buffer_get_str_len(const struct str_buffer *sb) {
if (sb) {
return sb->sz;
}
return 0;
}
void str_buffer_free(struct str_buffer *sb)
{
if(sb) {
free(sb->buffer);
free(sb);
}
void str_buffer_free(struct str_buffer *sb) {
if (sb) {
free(sb->buffer);
free(sb);
}
}
///////////////////////////////////////////////

View File

@ -31,12 +31,12 @@
#ifndef __TURN_HTTP_SERVER__
#define __TURN_HTTP_SERVER__
#include "ns_turn_utils.h"
#include "ns_turn_server.h"
#include "apputils.h"
#include "ns_turn_server.h"
#include "ns_turn_utils.h"
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
@ -44,40 +44,33 @@ extern "C" {
///////// HTTP REQUEST //////////
enum _HTTP_REQUEST_TYPE {
HRT_UNKNOWN=0,
HRT_GET,
HRT_HEAD,
HRT_POST,
HRT_PUT,
HRT_DELETE
};
enum _HTTP_REQUEST_TYPE { HRT_UNKNOWN = 0, HRT_GET, HRT_HEAD, HRT_POST, HRT_PUT, HRT_DELETE };
typedef enum _HTTP_REQUEST_TYPE HTTP_REQUEST_TYPE;
struct http_headers;
struct http_request {
HTTP_REQUEST_TYPE rtype;
char *path;
struct http_headers *headers;
HTTP_REQUEST_TYPE rtype;
char *path;
struct http_headers *headers;
};
struct http_request* parse_http_request(char* request);
const char *get_http_header_value(const struct http_request *request, const char* key, const char* def);
struct http_request *parse_http_request(char *request);
const char *get_http_header_value(const struct http_request *request, const char *key, const char *def);
void free_http_request(struct http_request *request);
const char* get_http_date_header(void);
const char *get_http_date_header(void);
////////////////////////////////////////////
struct str_buffer;
struct str_buffer* str_buffer_new(void);
void str_buffer_append(struct str_buffer* sb, const char* str);
void str_buffer_append_sz(struct str_buffer* sb, size_t sz);
void str_buffer_append_sid(struct str_buffer* sb, turnsession_id sid);
const char* str_buffer_get_str(const struct str_buffer *sb);
struct str_buffer *str_buffer_new(void);
void str_buffer_append(struct str_buffer *sb, const char *str);
void str_buffer_append_sz(struct str_buffer *sb, size_t sz);
void str_buffer_append_sid(struct str_buffer *sb, turnsession_id sid);
const char *str_buffer_get_str(const struct str_buffer *sb);
size_t str_buffer_get_str_len(const struct str_buffer *sb);
void str_buffer_free(struct str_buffer *sb);
@ -93,4 +86,3 @@ void handle_http_echo(ioa_socket_handle s);
#endif
/// __TURN_HTTP_SERVER__///

File diff suppressed because it is too large Load Diff

View File

@ -53,11 +53,11 @@ extern "C" {
/* printf type checking feature in GCC and some other compilers */
#if __GNUC__
# define TELNET_GNU_PRINTF(f,a) __attribute__((format(printf, f, a))) /*!< internal helper */
# define TELNET_GNU_SENTINEL __attribute__((sentinel)) /*!< internal helper */
#define TELNET_GNU_PRINTF(f, a) __attribute__((format(printf, f, a))) /*!< internal helper */
#define TELNET_GNU_SENTINEL __attribute__((sentinel)) /*!< internal helper */
#else
# define TELNET_GNU_PRINTF(f,a) /*!< internal helper */
# define TELNET_GNU_SENTINEL /*!< internal helper */
#define TELNET_GNU_PRINTF(f, a) /*!< internal helper */
#define TELNET_GNU_SENTINEL /*!< internal helper */
#endif
/* Disable environ macro for Visual C++ 2015. */
@ -178,168 +178,168 @@ typedef struct telnet_telopt_t telnet_telopt_t;
/*! \name Telnet state tracker flags. */
/*@{*/
/*! Control behavior of telnet state tracker. */
#define TELNET_FLAG_PROXY (1<<0)
#define TELNET_FLAG_NVT_EOL (1<<1)
#define TELNET_FLAG_PROXY (1 << 0)
#define TELNET_FLAG_NVT_EOL (1 << 1)
/* Internal-only bits in option flags */
#define TELNET_FLAG_TRANSMIT_BINARY (1<<5)
#define TELNET_FLAG_RECEIVE_BINARY (1<<6)
#define TELNET_PFLAG_DEFLATE (1<<7)
#define TELNET_FLAG_TRANSMIT_BINARY (1 << 5)
#define TELNET_FLAG_RECEIVE_BINARY (1 << 6)
#define TELNET_PFLAG_DEFLATE (1 << 7)
/*@}*/
/*!
* error codes
/*!
* error codes
*/
enum telnet_error_t {
TELNET_EOK = 0, /*!< no error */
TELNET_EBADVAL, /*!< invalid parameter, or API misuse */
TELNET_ENOMEM, /*!< memory allocation failure */
TELNET_EOVERFLOW, /*!< data exceeds buffer size */
TELNET_EPROTOCOL, /*!< invalid sequence of special bytes */
TELNET_ECOMPRESS /*!< error handling compressed streams */
TELNET_EOK = 0, /*!< no error */
TELNET_EBADVAL, /*!< invalid parameter, or API misuse */
TELNET_ENOMEM, /*!< memory allocation failure */
TELNET_EOVERFLOW, /*!< data exceeds buffer size */
TELNET_EPROTOCOL, /*!< invalid sequence of special bytes */
TELNET_ECOMPRESS /*!< error handling compressed streams */
};
typedef enum telnet_error_t telnet_error_t; /*!< Error code type. */
/*!
* event codes
/*!
* event codes
*/
enum telnet_event_type_t {
TELNET_EV_DATA = 0, /*!< raw text data has been received */
TELNET_EV_SEND, /*!< data needs to be sent to the peer */
TELNET_EV_IAC, /*!< generic IAC code received */
TELNET_EV_WILL, /*!< WILL option negotiation received */
TELNET_EV_WONT, /*!< WONT option neogitation received */
TELNET_EV_DO, /*!< DO option negotiation received */
TELNET_EV_DONT, /*!< DONT option negotiation received */
TELNET_EV_SUBNEGOTIATION, /*!< sub-negotiation data received */
TELNET_EV_COMPRESS, /*!< compression has been enabled */
TELNET_EV_ZMP, /*!< ZMP command has been received */
TELNET_EV_TTYPE, /*!< TTYPE command has been received */
TELNET_EV_ENVIRON, /*!< ENVIRON command has been received */
TELNET_EV_MSSP, /*!< MSSP command has been received */
TELNET_EV_WARNING, /*!< recoverable error has occured */
TELNET_EV_ERROR /*!< non-recoverable error has occured */
TELNET_EV_DATA = 0, /*!< raw text data has been received */
TELNET_EV_SEND, /*!< data needs to be sent to the peer */
TELNET_EV_IAC, /*!< generic IAC code received */
TELNET_EV_WILL, /*!< WILL option negotiation received */
TELNET_EV_WONT, /*!< WONT option neogitation received */
TELNET_EV_DO, /*!< DO option negotiation received */
TELNET_EV_DONT, /*!< DONT option negotiation received */
TELNET_EV_SUBNEGOTIATION, /*!< sub-negotiation data received */
TELNET_EV_COMPRESS, /*!< compression has been enabled */
TELNET_EV_ZMP, /*!< ZMP command has been received */
TELNET_EV_TTYPE, /*!< TTYPE command has been received */
TELNET_EV_ENVIRON, /*!< ENVIRON command has been received */
TELNET_EV_MSSP, /*!< MSSP command has been received */
TELNET_EV_WARNING, /*!< recoverable error has occured */
TELNET_EV_ERROR /*!< non-recoverable error has occured */
};
typedef enum telnet_event_type_t telnet_event_type_t; /*!< Telnet event type. */
/*!
* environ/MSSP command information
/*!
* environ/MSSP command information
*/
struct telnet_environ_t {
unsigned char type; /*!< either TELNET_ENVIRON_VAR or TELNET_ENVIRON_USERVAR */
char *var; /*!< name of the variable being set */
char *value; /*!< value of variable being set; empty string if no value */
unsigned char type; /*!< either TELNET_ENVIRON_VAR or TELNET_ENVIRON_USERVAR */
char *var; /*!< name of the variable being set */
char *value; /*!< value of variable being set; empty string if no value */
};
/*!
* event information
/*!
* event information
*/
union telnet_event_t {
/*!
* \brief Event type
*
* The type field will determine which of the other event structure fields
* have been filled in. For instance, if the event type is TELNET_EV_ZMP,
* then the zmp event field (and ONLY the zmp event field) will be filled
* in.
*/
enum telnet_event_type_t type;
/*!
* \brief Event type
*
* The type field will determine which of the other event structure fields
* have been filled in. For instance, if the event type is TELNET_EV_ZMP,
* then the zmp event field (and ONLY the zmp event field) will be filled
* in.
*/
enum telnet_event_type_t type;
/*!
* data event: for DATA and SEND events
*/
struct data_t {
enum telnet_event_type_t _type; /*!< alias for type */
const char *buffer; /*!< byte buffer */
size_t size; /*!< number of bytes in buffer */
} data;
/*!
* data event: for DATA and SEND events
*/
struct data_t {
enum telnet_event_type_t _type; /*!< alias for type */
const char *buffer; /*!< byte buffer */
size_t size; /*!< number of bytes in buffer */
} data;
/*!
* WARNING and ERROR events
*/
struct error_t {
enum telnet_event_type_t _type; /*!< alias for type */
const char *file; /*!< file the error occured in */
const char *func; /*!< function the error occured in */
const char *msg; /*!< error message string */
int line; /*!< line of file error occured on */
telnet_error_t errcode; /*!< error code */
} error;
/*!
* WARNING and ERROR events
*/
struct error_t {
enum telnet_event_type_t _type; /*!< alias for type */
const char *file; /*!< file the error occured in */
const char *func; /*!< function the error occured in */
const char *msg; /*!< error message string */
int line; /*!< line of file error occured on */
telnet_error_t errcode; /*!< error code */
} error;
/*!
* command event: for IAC
*/
struct iac_t {
enum telnet_event_type_t _type; /*!< alias for type */
unsigned char cmd; /*!< telnet command received */
} iac;
/*!
* command event: for IAC
*/
struct iac_t {
enum telnet_event_type_t _type; /*!< alias for type */
unsigned char cmd; /*!< telnet command received */
} iac;
/*!
* negotiation event: WILL, WONT, DO, DONT
*/
struct negotiate_t {
enum telnet_event_type_t _type; /*!< alias for type */
unsigned char telopt; /*!< option being negotiated */
} neg;
/*!
* negotiation event: WILL, WONT, DO, DONT
*/
struct negotiate_t {
enum telnet_event_type_t _type; /*!< alias for type */
unsigned char telopt; /*!< option being negotiated */
} neg;
/*!
* subnegotiation event
*/
struct subnegotiate_t {
enum telnet_event_type_t _type; /*!< alias for type */
const char *buffer; /*!< data of sub-negotiation */
size_t size; /*!< number of bytes in buffer */
unsigned char telopt; /*!< option code for negotiation */
} sub;
/*!
* subnegotiation event
*/
struct subnegotiate_t {
enum telnet_event_type_t _type; /*!< alias for type */
const char *buffer; /*!< data of sub-negotiation */
size_t size; /*!< number of bytes in buffer */
unsigned char telopt; /*!< option code for negotiation */
} sub;
/*!
* ZMP event
*/
struct zmp_t {
enum telnet_event_type_t _type; /*!< alias for type */
const char **argv; /*!< array of argument string */
size_t argc; /*!< number of elements in argv */
} zmp;
/*!
* ZMP event
*/
struct zmp_t {
enum telnet_event_type_t _type; /*!< alias for type */
const char **argv; /*!< array of argument string */
size_t argc; /*!< number of elements in argv */
} zmp;
/*!
* TTYPE event
*/
struct ttype_t {
enum telnet_event_type_t _type; /*!< alias for type */
unsigned char cmd; /*!< TELNET_TTYPE_IS or TELNET_TTYPE_SEND */
const char* name; /*!< terminal type name (IS only) */
} ttype;
/*!
* TTYPE event
*/
struct ttype_t {
enum telnet_event_type_t _type; /*!< alias for type */
unsigned char cmd; /*!< TELNET_TTYPE_IS or TELNET_TTYPE_SEND */
const char *name; /*!< terminal type name (IS only) */
} ttype;
/*!
* COMPRESS event
*/
struct compress_t {
enum telnet_event_type_t _type; /*!< alias for type */
unsigned char state; /*!< 1 if compression is enabled,
0 if disabled */
} compress;
/*!
* COMPRESS event
*/
struct compress_t {
enum telnet_event_type_t _type; /*!< alias for type */
unsigned char state; /*!< 1 if compression is enabled,
0 if disabled */
} compress;
/*!
* ENVIRON/NEW-ENVIRON event
*/
struct environ_t {
enum telnet_event_type_t _type; /*!< alias for type */
const struct telnet_environ_t *values; /*!< array of variable values */
size_t size; /*!< number of elements in values */
unsigned char cmd; /*!< SEND, IS, or INFO */
} environ;
/*!
* MSSP event
*/
struct mssp_t {
enum telnet_event_type_t _type; /*!< alias for type */
const struct telnet_environ_t *values; /*!< array of variable values */
size_t size; /*!< number of elements in values */
} mssp;
/*!
* ENVIRON/NEW-ENVIRON event
*/
struct environ_t {
enum telnet_event_type_t _type; /*!< alias for type */
const struct telnet_environ_t *values; /*!< array of variable values */
size_t size; /*!< number of elements in values */
unsigned char cmd; /*!< SEND, IS, or INFO */
} environ;
/*!
* MSSP event
*/
struct mssp_t {
enum telnet_event_type_t _type; /*!< alias for type */
const struct telnet_environ_t *values; /*!< array of variable values */
size_t size; /*!< number of elements in values */
} mssp;
};
/*!
/*!
* \brief event handler
*
* This is the type of function that must be passed to
@ -351,20 +351,19 @@ union telnet_event_t {
* \param event Event structure with details about the event
* \param user_data User-supplied pointer
*/
typedef void (*telnet_event_handler_t)(telnet_t *telnet,
telnet_event_t *event, void *user_data);
typedef void (*telnet_event_handler_t)(telnet_t *telnet, telnet_event_t *event, void *user_data);
/*!
* telopt support table element; use telopt of -1 for end marker
/*!
* telopt support table element; use telopt of -1 for end marker
*/
struct telnet_telopt_t {
short telopt; /*!< one of the TELOPT codes or -1 */
unsigned char us; /*!< TELNET_WILL or TELNET_WONT */
unsigned char him; /*!< TELNET_DO or TELNET_DONT */
short telopt; /*!< one of the TELOPT codes or -1 */
unsigned char us; /*!< TELNET_WILL or TELNET_WONT */
unsigned char him; /*!< TELNET_DO or TELNET_DONT */
};
/*!
* state tracker -- private data structure
/*!
* state tracker -- private data structure
*/
struct telnet_t;
@ -381,8 +380,8 @@ struct telnet_t;
* \param user_data Optional data pointer that will be passsed to eh.
* \return Telnet state tracker object.
*/
extern telnet_t* telnet_init(const telnet_telopt_t *telopts,
telnet_event_handler_t eh, unsigned char flags, void *user_data);
extern telnet_t *telnet_init(const telnet_telopt_t *telopts, telnet_event_handler_t eh, unsigned char flags,
void *user_data);
/*!
* \brief Free up any memory allocated by a state tracker.
@ -407,8 +406,7 @@ extern void telnet_free(telnet_t *telnet);
* \param buffer Pointer to byte buffer.
* \param size Number of bytes pointed to by buffer.
*/
extern void telnet_recv(telnet_t *telnet, const char *buffer,
size_t size);
extern void telnet_recv(telnet_t *telnet, const char *buffer, size_t size);
/*!
* \brief Send a telnet command.
@ -429,8 +427,7 @@ extern void telnet_iac(telnet_t *telnet, unsigned char cmd);
* \param cmd TELNET_WILL, TELNET_WONT, TELNET_DO, or TELNET_DONT.
* \param opt One of the TELNET_TELOPT_* values.
*/
extern void telnet_negotiate(telnet_t *telnet, unsigned char cmd,
unsigned char opt);
extern void telnet_negotiate(telnet_t *telnet, unsigned char cmd, unsigned char opt);
/*!
* Send non-command data (escapes IAC bytes).
@ -439,8 +436,7 @@ extern void telnet_negotiate(telnet_t *telnet, unsigned char cmd,
* \param buffer Buffer of bytes to send.
* \param size Number of bytes to send.
*/
extern void telnet_send(telnet_t *telnet,
const char *buffer, size_t size);
extern void telnet_send(telnet_t *telnet, const char *buffer, size_t size);
/*!
* Send non-command text (escapes IAC bytes and translates
@ -450,8 +446,7 @@ extern void telnet_send(telnet_t *telnet,
* \param buffer Buffer of bytes to send.
* \param size Number of bytes to send.
*/
extern void telnet_send_text(telnet_t *telnet,
const char *buffer, size_t size);
extern void telnet_send_text(telnet_t *telnet, const char *buffer, size_t size);
/*!
* \brief Begin a sub-negotiation command.
@ -463,8 +458,7 @@ extern void telnet_send_text(telnet_t *telnet,
* \param telnet Telnet state tracker object.
* \param telopt One of the TELNET_TELOPT_* values.
*/
extern void telnet_begin_sb(telnet_t *telnet,
unsigned char telopt);
extern void telnet_begin_sb(telnet_t *telnet, unsigned char telopt);
/*!
* \brief Finish a sub-negotiation command.
@ -489,8 +483,7 @@ extern void telnet_begin_sb(telnet_t *telnet,
* \param buffer Byte buffer for sub-negotiation data.
* \param size Number of bytes to use for sub-negotiation data.
*/
extern void telnet_subnegotiation(telnet_t *telnet, unsigned char telopt,
const char *buffer, size_t size);
extern void telnet_subnegotiation(telnet_t *telnet, unsigned char telopt, const char *buffer, size_t size);
/*!
* \brief Begin sending compressed data.
@ -520,8 +513,7 @@ extern void telnet_begin_compress2(telnet_t *telnet);
* \param fmt Format string.
* \return Number of bytes sent.
*/
extern int telnet_printf(telnet_t *telnet, const char *fmt, ...)
TELNET_GNU_PRINTF(2, 3);
extern int telnet_printf(telnet_t *telnet, const char *fmt, ...) TELNET_GNU_PRINTF(2, 3);
/*!
* \brief Send formatted data.
@ -541,8 +533,7 @@ extern int telnet_vprintf(telnet_t *telnet, const char *fmt, va_list va);
* \param fmt Format string.
* \return Number of bytes sent.
*/
extern int telnet_raw_printf(telnet_t *telnet, const char *fmt, ...)
TELNET_GNU_PRINTF(2, 3);
extern int telnet_raw_printf(telnet_t *telnet, const char *fmt, ...) TELNET_GNU_PRINTF(2, 3);
/*!
* \brief Send formatted data (no newline escaping).
@ -577,8 +568,7 @@ extern void telnet_begin_newenviron(telnet_t *telnet, unsigned char type);
* TELNET_ENVIRON_VALUE.
* \param string Variable name or value.
*/
extern void telnet_newenviron_value(telnet_t* telnet, unsigned char type,
const char *string);
extern void telnet_newenviron_value(telnet_t *telnet, unsigned char type, const char *string);
/*!
* \brief Finish a NEW-ENVIRON command.
@ -629,7 +619,7 @@ extern void telnet_ttype_send(telnet_t *telnet);
* \param telnet Telnet state tracker object.
* \param ttype Name of the terminal-type being sent.
*/
extern void telnet_ttype_is(telnet_t *telnet, const char* ttype);
extern void telnet_ttype_is(telnet_t *telnet, const char *ttype);
/*!
* \brief Send a ZMP command.

File diff suppressed because it is too large Load Diff

View File

@ -31,11 +31,11 @@
#if !defined(__MAIN_RELAY__)
#define __MAIN_RELAY__
#include <stdlib.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <limits.h>
#include <locale.h>
@ -44,39 +44,38 @@
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <getopt.h>
#if defined(__unix__) || defined(unix) || defined(__APPLE__) \
|| defined(__DARWIN__) || defined(__MACH__)
#if defined(__unix__) || defined(unix) || defined(__APPLE__) || defined(__DARWIN__) || defined(__MACH__)
#include <ifaddrs.h>
#include <libgen.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/time.h>
#include <sys/utsname.h>
#include <pwd.h>
#include <grp.h>
#include <pwd.h>
#endif
#include <event2/bufferevent.h>
#include <event2/buffer.h>
#include <event2/bufferevent.h>
#include "ns_turn_openssl.h"
#include "ns_turn_utils.h"
#include "ns_turn_khash.h"
#include "ns_turn_utils.h"
#include "userdb.h"
#include "turn_admin_server.h"
#include "userdb.h"
#include "tls_listener.h"
#include "dtls_listener.h"
#include "tls_listener.h"
#include "ns_turn_server.h"
#include "ns_turn_maps.h"
#include "ns_turn_server.h"
#include "apputils.h"
@ -88,7 +87,7 @@
#include <openssl/ssl.h>
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
#include <openssl/modes.h>
#include <openssl/modes.h>
#endif
#if !defined(TURN_NO_SYSTEMD)
@ -117,60 +116,52 @@ extern "C" {
/////////// TYPES ///////////////////////////////////
enum _DH_KEY_SIZE {
DH_566,
DH_1066,
DH_2066,
DH_CUSTOM
};
enum _DH_KEY_SIZE { DH_566, DH_1066, DH_2066, DH_CUSTOM };
typedef enum _DH_KEY_SIZE DH_KEY_SIZE;
///////// LISTENER SERVER TYPES /////////////////////
struct message_to_listener_to_client {
ioa_addr origin;
ioa_addr destination;
ioa_network_buffer_handle nbh;
ioa_addr origin;
ioa_addr destination;
ioa_network_buffer_handle nbh;
};
enum _MESSAGE_TO_LISTENER_TYPE {
LMT_UNKNOWN,
LMT_TO_CLIENT
};
enum _MESSAGE_TO_LISTENER_TYPE { LMT_UNKNOWN, LMT_TO_CLIENT };
typedef enum _MESSAGE_TO_LISTENER_TYPE MESSAGE_TO_LISTENER_TYPE;
struct message_to_listener {
MESSAGE_TO_LISTENER_TYPE t;
union {
struct message_to_listener_to_client tc;
} m;
MESSAGE_TO_LISTENER_TYPE t;
union {
struct message_to_listener_to_client tc;
} m;
};
struct listener_server {
rtcp_map* rtcpmap;
turnipports* tp;
struct event_base* event_base;
ioa_engine_handle ioa_eng;
struct bufferevent *in_buf;
struct bufferevent *out_buf;
char **addrs;
ioa_addr **encaddrs;
size_t addrs_number;
size_t services_number;
dtls_listener_relay_server_type ***udp_services;
dtls_listener_relay_server_type ***dtls_services;
dtls_listener_relay_server_type ***aux_udp_services;
rtcp_map *rtcpmap;
turnipports *tp;
struct event_base *event_base;
ioa_engine_handle ioa_eng;
struct bufferevent *in_buf;
struct bufferevent *out_buf;
char **addrs;
ioa_addr **encaddrs;
size_t addrs_number;
size_t services_number;
dtls_listener_relay_server_type ***udp_services;
dtls_listener_relay_server_type ***dtls_services;
dtls_listener_relay_server_type ***aux_udp_services;
};
enum _NET_ENG_VERSION {
NEV_UNKNOWN=0,
NEV_MIN,
NEV_UDP_SOCKET_PER_SESSION=NEV_MIN,
NEV_UDP_SOCKET_PER_ENDPOINT,
NEV_UDP_SOCKET_PER_THREAD,
NEV_MAX=NEV_UDP_SOCKET_PER_THREAD,
NEV_TOTAL
NEV_UNKNOWN = 0,
NEV_MIN,
NEV_UDP_SOCKET_PER_SESSION = NEV_MIN,
NEV_UDP_SOCKET_PER_ENDPOINT,
NEV_UDP_SOCKET_PER_THREAD,
NEV_MAX = NEV_UDP_SOCKET_PER_THREAD,
NEV_TOTAL
};
typedef enum _NET_ENG_VERSION NET_ENG_VERSION;
@ -179,16 +170,16 @@ typedef enum _NET_ENG_VERSION NET_ENG_VERSION;
typedef struct _turn_params_ {
//////////////// OpenSSL group //////////////////////
//////////////// OpenSSL group //////////////////////
SSL_CTX *tls_ctx;
SSL_CTX *dtls_ctx;
DH_KEY_SIZE dh_key_size;
char cipher_list[1025];
char ec_curve_name[33];
char ca_cert_file[1025];
char cert_file[1025];
char pkey_file[1025];
@ -204,7 +195,7 @@ typedef struct _turn_params_ {
struct event *tls_ctx_update_ev;
TURN_MUTEX_DECLARE(tls_mutex)
//////////////// Common params ////////////////////
//////////////// Common params ////////////////////
int verbose;
int turn_daemon;
@ -228,7 +219,7 @@ typedef struct _turn_params_ {
int no_udp;
int no_tcp;
int tcp_use_proxy;
vint no_tcp_relay;
vint no_udp_relay;
@ -243,9 +234,9 @@ typedef struct _turn_params_ {
ip_range_list_t ip_blacklist;
NET_ENG_VERSION net_engine_version;
const char* net_engine_version_txt[NEV_TOTAL];
const char *net_engine_version_txt[NEV_TOTAL];
//////////////// Relay servers /////////////
//////////////// Relay servers /////////////
uint16_t min_port;
uint16_t max_port;
@ -268,26 +259,26 @@ typedef struct _turn_params_ {
turnserver_id general_relay_servers_number;
turnserver_id udp_relay_servers_number;
////////////// Auth server ////////////////
////////////// Auth server ////////////////
char oauth_server_name[1025];
char domain[1025];
int oauth;
/////////////// AUX SERVERS ////////////////
/////////////// AUX SERVERS ////////////////
turn_server_addrs_list_t aux_servers_list;
int udp_self_balance;
/////////////// ALTERNATE SERVERS ////////////////
/////////////// ALTERNATE SERVERS ////////////////
turn_server_addrs_list_t alternate_servers_list;
turn_server_addrs_list_t tls_alternate_servers_list;
/////////////// stop server ////////////////
/////////////// stop server ////////////////
int stop_turn_server;
////////////// MISC PARAMS ////////////////
////////////// MISC PARAMS ////////////////
vint stun_only;
vint no_stun;
@ -311,12 +302,11 @@ typedef struct _turn_params_ {
int prometheus_port;
int prometheus_username_labels;
/////// Users DB ///////////
/////// Users DB ///////////
default_users_db_t default_users_db;
/////// CPUs //////////////
/////// CPUs //////////////
unsigned long cpus;
@ -338,15 +328,15 @@ extern turn_params_t turn_params;
//////////////// Listener server /////////////////
static inline int get_alt_listener_port(void) {
if(turn_params.alt_listener_port<1)
return turn_params.listener_port + 1;
return turn_params.alt_listener_port;
if (turn_params.alt_listener_port < 1)
return turn_params.listener_port + 1;
return turn_params.alt_listener_port;
}
static inline int get_alt_tls_listener_port(void) {
if(turn_params.alt_tls_listener_port<1)
return turn_params.tls_listener_port + 1;
return turn_params.alt_tls_listener_port;
if (turn_params.alt_tls_listener_port < 1)
return turn_params.tls_listener_port + 1;
return turn_params.alt_tls_listener_port;
}
void add_aux_server(const char *saddr);
@ -358,8 +348,8 @@ void del_tls_alternate_server(const char *saddr);
////////// Addrs ////////////////////
void add_listener_addr(const char* addr);
int add_relay_addr(const char* addr);
void add_listener_addr(const char *addr);
int add_relay_addr(const char *addr);
////////// SSL CTX ////////////////////
void set_ssl_ctx(ioa_engine_handle e, turn_params_t *params);
@ -385,21 +375,19 @@ void set_max_bps(band_limit_t value);
///////// AES ENCRYPTION AND DECRYPTION ////////
struct ctr_state {
unsigned char ivec[16];
unsigned int num;
unsigned char ecount[16];
unsigned char ivec[16];
unsigned int num;
unsigned char ecount[16];
};
void generate_aes_128_key(char* filePath, unsigned char* returnedKey);
unsigned char *base64encode (const void *b64_encode_this, int encode_this_many_bytes);
void encrypt_aes_128(unsigned char* in, const unsigned char* mykey);
unsigned char *base64decode (const void *b64_decode_this, int decode_this_many_bytes);
void decrypt_aes_128(char* in, const unsigned char* mykey);
void generate_aes_128_key(char *filePath, unsigned char *returnedKey);
unsigned char *base64encode(const void *b64_encode_this, int encode_this_many_bytes);
void encrypt_aes_128(unsigned char *in, const unsigned char *mykey);
unsigned char *base64decode(const void *b64_decode_this, int decode_this_many_bytes);
void decrypt_aes_128(char *in, const unsigned char *mykey);
int decodedTextSize(char *input);
char* decryptPassword(char* in, const unsigned char* mykey);
char *decryptPassword(char *in, const unsigned char *mykey);
int init_ctr(struct ctr_state *state, const unsigned char iv[8]);
///////////////////////////////
#ifdef __cplusplus

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -35,19 +35,19 @@
#ifndef __IOA_LIBIMPL__
#define __IOA_LIBIMPL__
#include <event2/event.h>
#include <event2/bufferevent.h>
#include <event2/buffer.h>
#include <event2/bufferevent.h>
#include <event2/event.h>
#include <event2/thread.h>
#include "ns_turn_openssl.h"
#include "ns_turn_ioalib.h"
#include "turn_ports.h"
#include "ns_turn_maps_rtcp.h"
#include "ns_turn_maps.h"
#include "ns_turn_maps_rtcp.h"
#include "ns_turn_server.h"
#include "turn_ports.h"
#include "apputils.h"
#include "stun_buffer.h"
@ -66,19 +66,19 @@ extern "C" {
#define MAX_BUFFER_QUEUE_SIZE_PER_ENGINE (64)
#define MAX_SOCKET_BUFFER_BACKLOG (16)
#define BUFFEREVENT_HIGH_WATERMARK (128<<10)
#define BUFFEREVENT_MAX_UDP_TO_TCP_WRITE (64<<9)
#define BUFFEREVENT_MAX_TCP_TO_TCP_WRITE (192<<10)
#define BUFFEREVENT_HIGH_WATERMARK (128 << 10)
#define BUFFEREVENT_MAX_UDP_TO_TCP_WRITE (64 << 9)
#define BUFFEREVENT_MAX_TCP_TO_TCP_WRITE (192 << 10)
typedef struct _stun_buffer_list_elem {
struct _stun_buffer_list_elem *next;
stun_buffer buf;
struct _stun_buffer_list_elem *next;
stun_buffer buf;
} stun_buffer_list_elem;
typedef struct _stun_buffer_list {
stun_buffer_list_elem *head;
stun_buffer_list_elem *tail;
size_t tsz;
stun_buffer_list_elem *head;
stun_buffer_list_elem *tail;
size_t tsz;
} stun_buffer_list;
/*
@ -86,40 +86,40 @@ typedef struct _stun_buffer_list {
*/
struct cb_socket_message {
turnserver_id id;
tcp_connection_id connection_id;
stun_tid tid;
ioa_socket_handle s;
int message_integrity;
ioa_net_data nd;
int can_resume;
turnserver_id id;
tcp_connection_id connection_id;
stun_tid tid;
ioa_socket_handle s;
int message_integrity;
ioa_net_data nd;
int can_resume;
};
struct cancelled_session_message {
turnsession_id id;
turnsession_id id;
};
struct relay_server {
turnserver_id id;
super_memory_t* sm;
struct event_base* event_base;
struct bufferevent *in_buf;
struct bufferevent *out_buf;
struct bufferevent *auth_in_buf;
struct bufferevent *auth_out_buf;
ioa_engine_handle ioa_eng;
turn_turnserver server;
pthread_t thr;
turnserver_id id;
super_memory_t *sm;
struct event_base *event_base;
struct bufferevent *in_buf;
struct bufferevent *out_buf;
struct bufferevent *auth_in_buf;
struct bufferevent *auth_out_buf;
ioa_engine_handle ioa_eng;
turn_turnserver server;
pthread_t thr;
};
struct message_to_relay {
MESSAGE_TO_RELAY_TYPE t;
struct relay_server *relay_server;
union {
struct socket_message sm;
struct cb_socket_message cb_sm;
struct cancelled_session_message csm;
} m;
MESSAGE_TO_RELAY_TYPE t;
struct relay_server *relay_server;
union {
struct socket_message sm;
struct cb_socket_message cb_sm;
struct cancelled_session_message csm;
} m;
};
struct relay_server;
@ -133,20 +133,19 @@ typedef int (*ioa_engine_udp_event_handler)(relay_server_handle rs, struct messa
#define PREDEF_TIMERS_NUM (14)
extern const int predef_timer_intervals[PREDEF_TIMERS_NUM];
struct _ioa_engine
{
struct _ioa_engine {
super_memory_t *sm;
struct event_base *event_base;
int deallocate_eb;
int verbose;
turnipports* tp;
turnipports *tp;
rtcp_map *map_rtcp;
stun_buffer_list bufs;
SSL_CTX *tls_ctx;
SSL_CTX *dtls_ctx;
turn_time_t jiffie; /* bandwidth check interval */
ioa_timer_handle timer_ev;
char cmsg[TURN_CMSG_SZ+1];
char cmsg[TURN_CMSG_SZ + 1];
int predef_timer_intervals[PREDEF_TIMERS_NUM];
struct timeval predef_timers[PREDEF_TIMERS_NUM];
/* Relays */
@ -161,71 +160,69 @@ struct _ioa_engine
#define SOCKET_MAGIC (0xABACADEF)
struct traffic_bytes {
band_limit_t jiffie_bytes_read;
band_limit_t jiffie_bytes_write;
band_limit_t jiffie_bytes_read;
band_limit_t jiffie_bytes_write;
};
struct _ioa_socket
{
evutil_socket_t fd;
struct _ioa_socket *parent_s;
uint32_t magic;
ur_addr_map *sockets_container; /* relay container for UDP sockets */
struct bufferevent *bev;
ioa_network_buffer_handle defer_nbh;
int family;
SOCKET_TYPE st;
SOCKET_APP_TYPE sat;
SSL* ssl;
uint32_t ssl_renegs;
int in_write;
int bound;
int local_addr_known;
ioa_addr local_addr;
int connected;
ioa_addr remote_addr;
ioa_engine_handle e;
struct event *read_event;
ioa_net_event_handler read_cb;
void *read_ctx;
int done;
ts_ur_super_session* session;
int current_df_relay_flag;
/* RFC6156: if IPv6 is involved, do not use DF: */
int do_not_use_df;
int tobeclosed;
int broken;
int default_ttl;
int current_ttl;
int default_tos;
int current_tos;
stun_buffer_list bufs;
turn_time_t jiffie; /* bandwidth check interval */
struct traffic_bytes data_traffic;
struct traffic_bytes control_traffic;
/* RFC 6062 ==>> */
//Connection session:
tcp_connection *sub_session;
//Connect:
struct bufferevent *conn_bev;
connect_cb conn_cb;
void *conn_arg;
//Accept:
struct evconnlistener *list_ev;
accept_cb acb;
void *acbarg;
/* <<== RFC 6062 */
void *special_session;
size_t special_session_size;
struct _ioa_socket {
evutil_socket_t fd;
struct _ioa_socket *parent_s;
uint32_t magic;
ur_addr_map *sockets_container; /* relay container for UDP sockets */
struct bufferevent *bev;
ioa_network_buffer_handle defer_nbh;
int family;
SOCKET_TYPE st;
SOCKET_APP_TYPE sat;
SSL *ssl;
uint32_t ssl_renegs;
int in_write;
int bound;
int local_addr_known;
ioa_addr local_addr;
int connected;
ioa_addr remote_addr;
ioa_engine_handle e;
struct event *read_event;
ioa_net_event_handler read_cb;
void *read_ctx;
int done;
ts_ur_super_session *session;
int current_df_relay_flag;
/* RFC6156: if IPv6 is involved, do not use DF: */
int do_not_use_df;
int tobeclosed;
int broken;
int default_ttl;
int current_ttl;
int default_tos;
int current_tos;
stun_buffer_list bufs;
turn_time_t jiffie; /* bandwidth check interval */
struct traffic_bytes data_traffic;
struct traffic_bytes control_traffic;
/* RFC 6062 ==>> */
// Connection session:
tcp_connection *sub_session;
// Connect:
struct bufferevent *conn_bev;
connect_cb conn_cb;
void *conn_arg;
// Accept:
struct evconnlistener *list_ev;
accept_cb acb;
void *acbarg;
/* <<== RFC 6062 */
void *special_session;
size_t special_session_size;
};
typedef struct _timer_event
{
struct event *ev;
ioa_engine_handle e;
ioa_timer_event_handler cb;
void *ctx;
char* txt;
typedef struct _timer_event {
struct event *ev;
ioa_engine_handle e;
ioa_timer_event_handler cb;
void *ctx;
char *txt;
} timer_event;
///////////////////////////////////
@ -233,24 +230,26 @@ typedef struct _timer_event
/* realm */
void create_default_realm(void);
int get_realm_data(char* name, realm_params_t* rp);
int get_realm_data(char *name, realm_params_t *rp);
/* engine handling */
ioa_engine_handle create_ioa_engine(super_memory_t *sm,
struct event_base *eb, turnipports* tp,
const char* relay_if,
size_t relays_number, char **relay_addrs, int default_relays,
int verbose
ioa_engine_handle create_ioa_engine(super_memory_t *sm, struct event_base *eb, turnipports *tp, const char *relay_if,
size_t relays_number, char **relay_addrs, int default_relays, int verbose
#if !defined(TURN_NO_HIREDIS)
,redis_stats_db_t* redis_stats_db
,
redis_stats_db_t *redis_stats_db
#endif
);
);
void ioa_engine_set_rtcp_map(ioa_engine_handle e, rtcp_map *rtcpmap);
ioa_socket_handle create_ioa_socket_from_fd(ioa_engine_handle e, ioa_socket_raw fd, ioa_socket_handle parent_s, SOCKET_TYPE st, SOCKET_APP_TYPE sat, const ioa_addr *remote_addr, const ioa_addr *local_addr);
ioa_socket_handle create_ioa_socket_from_ssl(ioa_engine_handle e, ioa_socket_handle parent_s, SSL* ssl, SOCKET_TYPE st, SOCKET_APP_TYPE sat, const ioa_addr *remote_addr, const ioa_addr *local_addr);
ioa_socket_handle create_ioa_socket_from_fd(ioa_engine_handle e, ioa_socket_raw fd, ioa_socket_handle parent_s,
SOCKET_TYPE st, SOCKET_APP_TYPE sat, const ioa_addr *remote_addr,
const ioa_addr *local_addr);
ioa_socket_handle create_ioa_socket_from_ssl(ioa_engine_handle e, ioa_socket_handle parent_s, SSL *ssl, SOCKET_TYPE st,
SOCKET_APP_TYPE sat, const ioa_addr *remote_addr,
const ioa_addr *local_addr);
int get_a_local_relay(int family, ioa_addr *relay_addr);
@ -262,9 +261,10 @@ void delete_socket_from_map(ioa_socket_handle s);
int is_connreset(void);
int would_block(void);
int udp_send(ioa_socket_handle s, const ioa_addr* dest_addr, const char* buffer, int len);
int udp_recvfrom(evutil_socket_t fd, ioa_addr* orig_addr, const ioa_addr *like_addr, char* buffer, int buf_size, int *ttl, int *tos, char *ecmsg, int flags, uint32_t *errcode);
int ssl_read(evutil_socket_t fd, SSL* ssl, ioa_network_buffer_handle nbh, int verbose);
int udp_send(ioa_socket_handle s, const ioa_addr *dest_addr, const char *buffer, int len);
int udp_recvfrom(evutil_socket_t fd, ioa_addr *orig_addr, const ioa_addr *like_addr, char *buffer, int buf_size,
int *ttl, int *tos, char *ecmsg, int flags, uint32_t *errcode);
int ssl_read(evutil_socket_t fd, SSL *ssl, ioa_network_buffer_handle nbh, int verbose);
int set_raw_socket_ttl_options(evutil_socket_t fd, int family);
int set_raw_socket_tos_options(evutil_socket_t fd, int family);
@ -282,8 +282,9 @@ int ioa_socket_check_bandwidth(ioa_socket_handle s, ioa_network_buffer_handle nb
///////////////////////// SUPER MEMORY ////////
#define allocate_super_memory_engine(e,size) allocate_super_memory_engine_func(e, size, __FILE__, __FUNCTION__, __LINE__)
void* allocate_super_memory_engine_func(ioa_engine_handle e, size_t size, const char* file, const char* func, int line);
#define allocate_super_memory_engine(e, size) \
allocate_super_memory_engine_func(e, size, __FILE__, __FUNCTION__, __LINE__)
void *allocate_super_memory_engine_func(ioa_engine_handle e, size_t size, const char *file, const char *func, int line);
/////////////////////////////////////////////////

View File

@ -52,10 +52,12 @@ typedef struct _super_memory super_memory_t;
void init_super_memory(void);
super_memory_t* new_super_memory_region(void);
super_memory_t *new_super_memory_region(void);
#define allocate_super_memory_region(region,size) allocate_super_memory_region_func(region, size, __FILE__, __FUNCTION__, __LINE__)
void* allocate_super_memory_region_func(super_memory_t *region, size_t size, const char* file, const char* func, int line);
#define allocate_super_memory_region(region, size) \
allocate_super_memory_region_func(region, size, __FILE__, __FUNCTION__, __LINE__)
void *allocate_super_memory_region_func(super_memory_t *region, size_t size, const char *file, const char *func,
int line);
/////////////////////////////////////////////////

View File

@ -1,10 +1,9 @@
#include "mainrelay.h"
#include "prom_server.h"
#include "mainrelay.h"
#include "ns_turn_utils.h"
#if !defined(TURN_NO_PROMETHEUS)
prom_counter_t *turn_traffic_rcvp;
prom_counter_t *turn_traffic_rcvb;
prom_counter_t *turn_traffic_sentp;
@ -27,9 +26,8 @@ prom_counter_t *turn_total_traffic_peer_sentb;
prom_gauge_t *turn_total_allocations;
void start_prometheus_server(void){
if (turn_params.prometheus == 0){
void start_prometheus_server(void) {
if (turn_params.prometheus == 0) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "prometheus collector disabled, not started\n");
return;
}
@ -44,45 +42,62 @@ void start_prometheus_server(void){
}
// Create traffic counter metrics
turn_traffic_rcvp = prom_collector_registry_must_register_metric(prom_counter_new("turn_traffic_rcvp", "Represents finished sessions received packets", nlabels, label));
turn_traffic_rcvb = prom_collector_registry_must_register_metric(prom_counter_new("turn_traffic_rcvb", "Represents finished sessions received bytes", nlabels, label));
turn_traffic_sentp = prom_collector_registry_must_register_metric(prom_counter_new("turn_traffic_sentp", "Represents finished sessions sent packets", nlabels, label));
turn_traffic_sentb = prom_collector_registry_must_register_metric(prom_counter_new("turn_traffic_sentb", "Represents finished sessions sent bytes", nlabels, label));
turn_traffic_rcvp = prom_collector_registry_must_register_metric(
prom_counter_new("turn_traffic_rcvp", "Represents finished sessions received packets", nlabels, label));
turn_traffic_rcvb = prom_collector_registry_must_register_metric(
prom_counter_new("turn_traffic_rcvb", "Represents finished sessions received bytes", nlabels, label));
turn_traffic_sentp = prom_collector_registry_must_register_metric(
prom_counter_new("turn_traffic_sentp", "Represents finished sessions sent packets", nlabels, label));
turn_traffic_sentb = prom_collector_registry_must_register_metric(
prom_counter_new("turn_traffic_sentb", "Represents finished sessions sent bytes", nlabels, label));
// Create finished sessions traffic for peers counter metrics
turn_traffic_peer_rcvp = prom_collector_registry_must_register_metric(prom_counter_new("turn_traffic_peer_rcvp", "Represents finished sessions peer received packets", nlabels, label));
turn_traffic_peer_rcvb = prom_collector_registry_must_register_metric(prom_counter_new("turn_traffic_peer_rcvb", "Represents finished sessions peer received bytes", nlabels, label));
turn_traffic_peer_sentp = prom_collector_registry_must_register_metric(prom_counter_new("turn_traffic_peer_sentp", "Represents finished sessions peer sent packets", nlabels, label));
turn_traffic_peer_sentb = prom_collector_registry_must_register_metric(prom_counter_new("turn_traffic_peer_sentb", "Represents finished sessions peer sent bytes", nlabels, label));
turn_traffic_peer_rcvp = prom_collector_registry_must_register_metric(
prom_counter_new("turn_traffic_peer_rcvp", "Represents finished sessions peer received packets", nlabels, label));
turn_traffic_peer_rcvb = prom_collector_registry_must_register_metric(
prom_counter_new("turn_traffic_peer_rcvb", "Represents finished sessions peer received bytes", nlabels, label));
turn_traffic_peer_sentp = prom_collector_registry_must_register_metric(
prom_counter_new("turn_traffic_peer_sentp", "Represents finished sessions peer sent packets", nlabels, label));
turn_traffic_peer_sentb = prom_collector_registry_must_register_metric(
prom_counter_new("turn_traffic_peer_sentb", "Represents finished sessions peer sent bytes", nlabels, label));
// Create total finished traffic counter metrics
turn_total_traffic_rcvp = prom_collector_registry_must_register_metric(prom_counter_new("turn_total_traffic_rcvp", "Represents total finished sessions received packets", 0, NULL));
turn_total_traffic_rcvb = prom_collector_registry_must_register_metric(prom_counter_new("turn_total_traffic_rcvb", "Represents total finished sessions received bytes", 0, NULL));
turn_total_traffic_sentp = prom_collector_registry_must_register_metric(prom_counter_new("turn_total_traffic_sentp", "Represents total finished sessions sent packets", 0, NULL));
turn_total_traffic_sentb = prom_collector_registry_must_register_metric(prom_counter_new("turn_total_traffic_sentb", "Represents total finished sessions sent bytes", 0, NULL));
turn_total_traffic_rcvp = prom_collector_registry_must_register_metric(
prom_counter_new("turn_total_traffic_rcvp", "Represents total finished sessions received packets", 0, NULL));
turn_total_traffic_rcvb = prom_collector_registry_must_register_metric(
prom_counter_new("turn_total_traffic_rcvb", "Represents total finished sessions received bytes", 0, NULL));
turn_total_traffic_sentp = prom_collector_registry_must_register_metric(
prom_counter_new("turn_total_traffic_sentp", "Represents total finished sessions sent packets", 0, NULL));
turn_total_traffic_sentb = prom_collector_registry_must_register_metric(
prom_counter_new("turn_total_traffic_sentb", "Represents total finished sessions sent bytes", 0, NULL));
// Create total finished sessions traffic for peers counter metrics
turn_total_traffic_peer_rcvp = prom_collector_registry_must_register_metric(prom_counter_new("turn_total_traffic_peer_rcvp", "Represents total finished sessions peer received packets", 0, NULL));
turn_total_traffic_peer_rcvb = prom_collector_registry_must_register_metric(prom_counter_new("turn_total_traffic_peer_rcvb", "Represents total finished sessions peer received bytes", 0, NULL));
turn_total_traffic_peer_sentp = prom_collector_registry_must_register_metric(prom_counter_new("turn_total_traffic_peer_sentp", "Represents total finished sessions peer sent packets", 0, NULL));
turn_total_traffic_peer_sentb = prom_collector_registry_must_register_metric(prom_counter_new("turn_total_traffic_peer_sentb", "Represents total finished sessions peer sent bytes", 0, NULL));
turn_total_traffic_peer_rcvp = prom_collector_registry_must_register_metric(prom_counter_new(
"turn_total_traffic_peer_rcvp", "Represents total finished sessions peer received packets", 0, NULL));
turn_total_traffic_peer_rcvb = prom_collector_registry_must_register_metric(prom_counter_new(
"turn_total_traffic_peer_rcvb", "Represents total finished sessions peer received bytes", 0, NULL));
turn_total_traffic_peer_sentp = prom_collector_registry_must_register_metric(prom_counter_new(
"turn_total_traffic_peer_sentp", "Represents total finished sessions peer sent packets", 0, NULL));
turn_total_traffic_peer_sentb = prom_collector_registry_must_register_metric(
prom_counter_new("turn_total_traffic_peer_sentb", "Represents total finished sessions peer sent bytes", 0, NULL));
// Create total allocations number gauge metric
turn_total_allocations = prom_collector_registry_must_register_metric(prom_gauge_new("turn_total_allocations", "Represents current allocations number", 1, (const char*[]) {"type"}));
turn_total_allocations = prom_collector_registry_must_register_metric(
prom_gauge_new("turn_total_allocations", "Represents current allocations number", 1, (const char *[]){"type"}));
promhttp_set_active_collector_registry(NULL);
unsigned int flags = MHD_USE_DUAL_STACK
unsigned int flags = MHD_USE_DUAL_STACK
#if MHD_USE_ERROR_LOG
| MHD_USE_ERROR_LOG
| MHD_USE_ERROR_LOG
#endif
;
;
if (MHD_is_feature_supported(MHD_FEATURE_EPOLL)) {
#if MHD_USE_EPOLL_INTERNAL_THREAD
#if MHD_USE_EPOLL_INTERNAL_THREAD
flags |= MHD_USE_EPOLL_INTERNAL_THREAD;
#else
flags |= MHD_USE_SELECT_INTERNALLY; //ubuntu 16.04
#endif
#else
flags |= MHD_USE_SELECT_INTERNALLY; // ubuntu 16.04
#endif
} else {
flags |= MHD_USE_SELECT_INTERNALLY;
}
@ -97,15 +112,16 @@ void start_prometheus_server(void){
return;
}
void prom_set_finished_traffic(const char* realm, const char* user, unsigned long rsvp, unsigned long rsvb, unsigned long sentp, unsigned long sentb, bool peer){
if (turn_params.prometheus == 1){
void prom_set_finished_traffic(const char *realm, const char *user, unsigned long rsvp, unsigned long rsvb,
unsigned long sentp, unsigned long sentb, bool peer) {
if (turn_params.prometheus == 1) {
const char *label[] = {realm, NULL};
if (turn_params.prometheus_username_labels){
if (turn_params.prometheus_username_labels) {
label[1] = user;
}
if (peer){
if (peer) {
prom_counter_add(turn_traffic_peer_rcvp, rsvp, label);
prom_counter_add(turn_traffic_peer_rcvb, rsvb, label);
prom_counter_add(turn_traffic_peer_sentp, sentp, label);
@ -130,22 +146,22 @@ void prom_set_finished_traffic(const char* realm, const char* user, unsigned lon
}
void prom_inc_allocation(SOCKET_TYPE type) {
if (turn_params.prometheus == 1){
prom_gauge_inc(turn_total_allocations, (const char*[]) {socket_type_name(type)});
if (turn_params.prometheus == 1) {
prom_gauge_inc(turn_total_allocations, (const char *[]){socket_type_name(type)});
}
}
void prom_dec_allocation(SOCKET_TYPE type) {
if (turn_params.prometheus == 1){
prom_gauge_dec(turn_total_allocations, (const char*[]) {socket_type_name(type)});
if (turn_params.prometheus == 1) {
prom_gauge_dec(turn_total_allocations, (const char *[]){socket_type_name(type)});
}
}
#else
void start_prometheus_server(void){
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "turnserver compiled without prometheus support\n");
return;
void start_prometheus_server(void) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "turnserver compiled without prometheus support\n");
return;
}
#endif /* TURN_NO_PROMETHEUS */

View File

@ -7,10 +7,12 @@
#if !defined(TURN_NO_PROMETHEUS)
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdbool.h>
#include "ns_turn_ioalib.h"
#ifdef __cplusplus
extern "C" {
@ -54,10 +56,10 @@ extern prom_gauge_t *turn_total_allocations_number;
extern "C" {
#endif
void start_prometheus_server(void);
void prom_set_finished_traffic(const char* realm, const char* user, unsigned long rsvp, unsigned long rsvb, unsigned long sentp, unsigned long sentb, bool peer);
void prom_set_finished_traffic(const char *realm, const char *user, unsigned long rsvp, unsigned long rsvb,
unsigned long sentp, unsigned long sentb, bool peer);
void prom_inc_allocation(SOCKET_TYPE type);
void prom_dec_allocation(SOCKET_TYPE type);
@ -71,4 +73,4 @@ void start_prometheus_server(void);
}
#endif /* __clplusplus */
#endif /* __PROM_SERVER_H__ */
#endif /* __PROM_SERVER_H__ */

View File

@ -33,277 +33,257 @@
#include "ns_turn_utils.h"
#include "tls_listener.h"
#include "ns_ioalib_impl.h"
#include "tls_listener.h"
#include <event2/listener.h>
///////////////////////////////////////////////////
#define FUNCSTART if(server && eve(server->verbose)) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"%s:%d:start\n",__FUNCTION__,__LINE__)
#define FUNCEND if(server && eve(server->verbose)) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"%s:%d:end\n",__FUNCTION__,__LINE__)
#define FUNCSTART \
if (server && eve(server->verbose)) \
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s:%d:start\n", __FUNCTION__, __LINE__)
#define FUNCEND \
if (server && eve(server->verbose)) \
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s:%d:end\n", __FUNCTION__, __LINE__)
struct tls_listener_relay_server_info
{
char ifname[1025];
ioa_addr addr;
ioa_engine_handle e;
int verbose;
struct evconnlistener *l;
struct evconnlistener *sctp_l;
struct message_to_relay sm;
ioa_engine_new_connection_event_handler connect_cb;
struct relay_server *relay_server;
struct tls_listener_relay_server_info {
char ifname[1025];
ioa_addr addr;
ioa_engine_handle e;
int verbose;
struct evconnlistener *l;
struct evconnlistener *sctp_l;
struct message_to_relay sm;
ioa_engine_new_connection_event_handler connect_cb;
struct relay_server *relay_server;
};
/////////////// io handlers ///////////////////
static void server_input_handler(struct evconnlistener *l, evutil_socket_t fd,
struct sockaddr *sa, int socklen, void *arg)
{
static void server_input_handler(struct evconnlistener *l, evutil_socket_t fd, struct sockaddr *sa, int socklen,
void *arg) {
UNUSED_ARG(l);
UNUSED_ARG(l);
tls_listener_relay_server_type * server = (tls_listener_relay_server_type*) arg;
tls_listener_relay_server_type *server = (tls_listener_relay_server_type *)arg;
if (!server)
{
return;
}
if (!server) {
return;
}
if(!(server->connect_cb)) {
socket_closesocket(fd);
return;
}
if (!(server->connect_cb)) {
socket_closesocket(fd);
return;
}
FUNCSTART;
FUNCSTART;
memcpy(&(server->sm.m.sm.nd.src_addr),sa,socklen);
memcpy(&(server->sm.m.sm.nd.src_addr), sa, socklen);
addr_debug_print(server->verbose, &(server->sm.m.sm.nd.src_addr),"tcp or tls connected to");
addr_debug_print(server->verbose, &(server->sm.m.sm.nd.src_addr), "tcp or tls connected to");
SOCKET_TYPE st = TENTATIVE_TCP_SOCKET;
SOCKET_TYPE st = TENTATIVE_TCP_SOCKET;
if(turn_params.tcp_use_proxy)
st = TCP_SOCKET_PROXY;
else if(turn_params.no_tls)
st = TCP_SOCKET;
else if(turn_params.no_tcp)
st = TLS_SOCKET;
if (turn_params.tcp_use_proxy)
st = TCP_SOCKET_PROXY;
else if (turn_params.no_tls)
st = TCP_SOCKET;
else if (turn_params.no_tcp)
st = TLS_SOCKET;
ioa_socket_handle ioas =
create_ioa_socket_from_fd(
server->e,
fd,
NULL,
st,
CLIENT_SOCKET,
&(server->sm.m.sm.nd.src_addr),
&(server->addr));
ioa_socket_handle ioas = create_ioa_socket_from_fd(server->e, fd, NULL, st, CLIENT_SOCKET,
&(server->sm.m.sm.nd.src_addr), &(server->addr));
if (ioas) {
if (ioas) {
server->sm.m.sm.nd.recv_ttl = TTL_IGNORE;
server->sm.m.sm.nd.recv_tos = TOS_IGNORE;
server->sm.m.sm.nd.nbh = NULL;
server->sm.m.sm.s = ioas;
server->sm.m.sm.can_resume = 1;
server->sm.relay_server = server->relay_server;
server->sm.m.sm.nd.recv_ttl = TTL_IGNORE;
server->sm.m.sm.nd.recv_tos = TOS_IGNORE;
server->sm.m.sm.nd.nbh = NULL;
server->sm.m.sm.s = ioas;
server->sm.m.sm.can_resume = 1;
server->sm.relay_server = server->relay_server;
int rc = server->connect_cb(server->e, &(server->sm));
int rc = server->connect_cb(server->e, &(server->sm));
if (rc < 0) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,
"Cannot create tcp or tls session\n");
}
} else {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,
"Cannot create ioa_socket from FD\n");
socket_closesocket(fd);
}
if (rc < 0) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot create tcp or tls session\n");
}
} else {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot create ioa_socket from FD\n");
socket_closesocket(fd);
}
FUNCEND ;
FUNCEND;
}
#if !defined(TURN_NO_SCTP)
static void sctp_server_input_handler(struct evconnlistener *l, evutil_socket_t fd,
struct sockaddr *sa, int socklen, void *arg)
{
static void sctp_server_input_handler(struct evconnlistener *l, evutil_socket_t fd, struct sockaddr *sa, int socklen,
void *arg) {
UNUSED_ARG(l);
UNUSED_ARG(l);
tls_listener_relay_server_type * server = (tls_listener_relay_server_type*) arg;
tls_listener_relay_server_type *server = (tls_listener_relay_server_type *)arg;
if (!server)
{
return;
}
if (!server) {
return;
}
if(!(server->connect_cb)) {
socket_closesocket(fd);
return;
}
if (!(server->connect_cb)) {
socket_closesocket(fd);
return;
}
FUNCSTART;
FUNCSTART;
memcpy(&(server->sm.m.sm.nd.src_addr),sa,socklen);
memcpy(&(server->sm.m.sm.nd.src_addr), sa, socklen);
addr_debug_print(server->verbose, &(server->sm.m.sm.nd.src_addr),"sctp or tls/sctp connected to");
addr_debug_print(server->verbose, &(server->sm.m.sm.nd.src_addr), "sctp or tls/sctp connected to");
SOCKET_TYPE st = TENTATIVE_SCTP_SOCKET;
SOCKET_TYPE st = TENTATIVE_SCTP_SOCKET;
if(turn_params.no_tls)
st = SCTP_SOCKET;
else if(turn_params.no_tcp)
st = TLS_SCTP_SOCKET;
if (turn_params.no_tls)
st = SCTP_SOCKET;
else if (turn_params.no_tcp)
st = TLS_SCTP_SOCKET;
ioa_socket_handle ioas =
create_ioa_socket_from_fd(
server->e,
fd,
NULL,
st,
CLIENT_SOCKET,
&(server->sm.m.sm.nd.src_addr),
&(server->addr));
ioa_socket_handle ioas = create_ioa_socket_from_fd(server->e, fd, NULL, st, CLIENT_SOCKET,
&(server->sm.m.sm.nd.src_addr), &(server->addr));
if (ioas) {
if (ioas) {
server->sm.m.sm.nd.recv_ttl = TTL_IGNORE;
server->sm.m.sm.nd.recv_tos = TOS_IGNORE;
server->sm.m.sm.nd.nbh = NULL;
server->sm.m.sm.s = ioas;
server->sm.m.sm.can_resume = 1;
server->sm.relay_server = server->relay_server;
server->sm.m.sm.nd.recv_ttl = TTL_IGNORE;
server->sm.m.sm.nd.recv_tos = TOS_IGNORE;
server->sm.m.sm.nd.nbh = NULL;
server->sm.m.sm.s = ioas;
server->sm.m.sm.can_resume = 1;
server->sm.relay_server = server->relay_server;
int rc = server->connect_cb(server->e, &(server->sm));
int rc = server->connect_cb(server->e, &(server->sm));
if (rc < 0) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,
"Cannot create sctp or tls/sctp session\n");
}
} else {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,
"Cannot create ioa_socket from FD\n");
socket_closesocket(fd);
}
if (rc < 0) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot create sctp or tls/sctp session\n");
}
} else {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot create ioa_socket from FD\n");
socket_closesocket(fd);
}
FUNCEND ;
FUNCEND;
}
#endif
///////////////////// operations //////////////////////////
static int create_server_listener(tls_listener_relay_server_type* server) {
static int create_server_listener(tls_listener_relay_server_type *server) {
FUNCSTART;
if(!server) return -1;
if (!server)
return -1;
evutil_socket_t tls_listen_fd = -1;
tls_listen_fd = socket(server->addr.ss.sa_family, CLIENT_STREAM_SOCKET_TYPE, CLIENT_STREAM_SOCKET_PROTOCOL);
if (tls_listen_fd < 0) {
perror("socket");
return -1;
perror("socket");
return -1;
}
if(sock_bind_to_device(tls_listen_fd, (unsigned char*)server->ifname)<0) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Cannot bind listener socket to device %s\n",server->ifname);
if (sock_bind_to_device(tls_listen_fd, (unsigned char *)server->ifname) < 0) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Cannot bind listener socket to device %s\n", server->ifname);
}
{
const int max_binding_time = 60;
int addr_bind_cycle = 0;
retry_addr_bind:
const int max_binding_time = 60;
int addr_bind_cycle = 0;
retry_addr_bind:
if(addr_bind(tls_listen_fd,&server->addr,1,1,TCP_SOCKET)<0) {
perror("Cannot bind local socket to addr");
char saddr[129];
addr_to_string(&server->addr,(uint8_t*)saddr);
TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING,"Cannot bind TLS/TCP listener socket to addr %s\n",saddr);
if(addr_bind_cycle++<max_binding_time) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Trying to bind TLS/TCP listener socket to addr %s, again...\n",saddr);
sleep(1);
goto retry_addr_bind;
}
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Fatal final failure: cannot bind TLS/TCP listener socket to addr %s\n",saddr);
exit(-1);
}
}
if (addr_bind(tls_listen_fd, &server->addr, 1, 1, TCP_SOCKET) < 0) {
perror("Cannot bind local socket to addr");
char saddr[129];
addr_to_string(&server->addr, (uint8_t *)saddr);
TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "Cannot bind TLS/TCP listener socket to addr %s\n", saddr);
if (addr_bind_cycle++ < max_binding_time) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Trying to bind TLS/TCP listener socket to addr %s, again...\n", saddr);
sleep(1);
goto retry_addr_bind;
}
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Fatal final failure: cannot bind TLS/TCP listener socket to addr %s\n",
saddr);
exit(-1);
}
}
socket_tcp_set_keepalive(tls_listen_fd,TCP_SOCKET);
socket_tcp_set_keepalive(tls_listen_fd, TCP_SOCKET);
socket_set_nonblocking(tls_listen_fd);
server->l = evconnlistener_new(server->e->event_base,
server_input_handler, server,
LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE,
1024, tls_listen_fd);
server->l = evconnlistener_new(server->e->event_base, server_input_handler, server,
LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, 1024, tls_listen_fd);
if(!(server->l)) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Cannot create TLS listener\n");
socket_closesocket(tls_listen_fd);
return -1;
if (!(server->l)) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Cannot create TLS listener\n");
socket_closesocket(tls_listen_fd);
return -1;
}
if(!turn_params.no_tcp && !turn_params.no_tls)
addr_debug_print(server->verbose, &server->addr,"TLS/TCP listener opened on ");
else if(!turn_params.no_tls)
addr_debug_print(server->verbose, &server->addr,"TLS listener opened on ");
else if(!turn_params.no_tcp)
addr_debug_print(server->verbose, &server->addr,"TCP listener opened on ");
if (!turn_params.no_tcp && !turn_params.no_tls)
addr_debug_print(server->verbose, &server->addr, "TLS/TCP listener opened on ");
else if (!turn_params.no_tls)
addr_debug_print(server->verbose, &server->addr, "TLS listener opened on ");
else if (!turn_params.no_tcp)
addr_debug_print(server->verbose, &server->addr, "TCP listener opened on ");
FUNCEND;
return 0;
}
#if !defined(TURN_NO_SCTP)
static int sctp_create_server_listener(tls_listener_relay_server_type* server) {
static int sctp_create_server_listener(tls_listener_relay_server_type *server) {
FUNCSTART;
if(!server) return -1;
if (!server)
return -1;
evutil_socket_t tls_listen_fd = -1;
tls_listen_fd = socket(server->addr.ss.sa_family, SCTP_CLIENT_STREAM_SOCKET_TYPE, SCTP_CLIENT_STREAM_SOCKET_PROTOCOL);
if (tls_listen_fd < 0) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Cannot create SCTP socket listener\n");
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot create SCTP socket listener\n");
return -1;
}
if(sock_bind_to_device(tls_listen_fd, (unsigned char*)server->ifname)<0) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Cannot bind listener socket to device %s\n",server->ifname);
if (sock_bind_to_device(tls_listen_fd, (unsigned char *)server->ifname) < 0) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Cannot bind listener socket to device %s\n", server->ifname);
}
if(addr_bind(tls_listen_fd,&server->addr,1,0,SCTP_SOCKET)<0) {
close(tls_listen_fd);
return -1;
if (addr_bind(tls_listen_fd, &server->addr, 1, 0, SCTP_SOCKET) < 0) {
close(tls_listen_fd);
return -1;
}
socket_tcp_set_keepalive(tls_listen_fd,SCTP_SOCKET);
socket_tcp_set_keepalive(tls_listen_fd, SCTP_SOCKET);
socket_set_nonblocking(tls_listen_fd);
server->sctp_l = evconnlistener_new(server->e->event_base,
sctp_server_input_handler, server,
LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE,
1024, tls_listen_fd);
server->sctp_l = evconnlistener_new(server->e->event_base, sctp_server_input_handler, server,
LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, 1024, tls_listen_fd);
if(!(server->sctp_l)) {
socket_closesocket(tls_listen_fd);
return -1;
if (!(server->sctp_l)) {
socket_closesocket(tls_listen_fd);
return -1;
}
if (!turn_params.no_tls)
addr_debug_print(server->verbose, &server->addr, "TLS/SCTP listener opened on ");
addr_debug_print(server->verbose, &server->addr, "TLS/SCTP listener opened on ");
else
addr_debug_print(server->verbose, &server->addr, "SCTP listener opened on ");
addr_debug_print(server->verbose, &server->addr, "SCTP listener opened on ");
FUNCEND;
@ -312,29 +292,26 @@ static int sctp_create_server_listener(tls_listener_relay_server_type* server) {
#endif
static int init_server(tls_listener_relay_server_type* server,
const char* ifname,
const char *local_address,
int port,
int verbose,
ioa_engine_handle e,
ioa_engine_new_connection_event_handler send_socket,
struct relay_server *relay_server) {
static int init_server(tls_listener_relay_server_type *server, const char *ifname, const char *local_address, int port,
int verbose, ioa_engine_handle e, ioa_engine_new_connection_event_handler send_socket,
struct relay_server *relay_server) {
if(!server) return -1;
if (!server)
return -1;
server->connect_cb = send_socket;
server->relay_server = relay_server;
if(ifname) STRCPY(server->ifname,ifname);
if (ifname)
STRCPY(server->ifname, ifname);
if(make_ioa_addr((const uint8_t*)local_address, port, &server->addr)<0) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Cannot create a TCP/TLS listener for address: %s\n",local_address);
return -1;
if (make_ioa_addr((const uint8_t *)local_address, port, &server->addr) < 0) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot create a TCP/TLS listener for address: %s\n", local_address);
return -1;
}
server->verbose=verbose;
server->verbose = verbose;
server->e = e;
#if !defined(TURN_NO_SCTP)
@ -346,23 +323,19 @@ static int init_server(tls_listener_relay_server_type* server,
///////////////////////////////////////////////////////////
tls_listener_relay_server_type *create_tls_listener_server(const char *ifname, const char *local_address, int port,
int verbose, ioa_engine_handle e,
ioa_engine_new_connection_event_handler send_socket,
struct relay_server *relay_server) {
tls_listener_relay_server_type* create_tls_listener_server(const char* ifname,
const char *local_address, int port, int verbose,
ioa_engine_handle e,
ioa_engine_new_connection_event_handler send_socket,
struct relay_server *relay_server)
{
tls_listener_relay_server_type *server =
(tls_listener_relay_server_type *)allocate_super_memory_engine(e, sizeof(tls_listener_relay_server_type));
tls_listener_relay_server_type* server =
(tls_listener_relay_server_type*) allocate_super_memory_engine(e,sizeof(tls_listener_relay_server_type));
if (init_server(server, ifname, local_address, port, verbose, e,
send_socket, relay_server) < 0) {
return NULL ;
} else {
return server;
}
if (init_server(server, ifname, local_address, port, verbose, e, send_socket, relay_server) < 0) {
return NULL;
} else {
return server;
}
}
//////////////////////////////////////////////////////////////////

View File

@ -48,11 +48,10 @@ typedef struct tls_listener_relay_server_info tls_listener_relay_server_type;
///////////////////////////////////////////
tls_listener_relay_server_type* create_tls_listener_server(const char* ifname,
const char *local_address, int port, int verbose,
ioa_engine_handle e,
ioa_engine_new_connection_event_handler send_socket,
struct relay_server *relay_server);
tls_listener_relay_server_type *create_tls_listener_server(const char *ifname, const char *local_address, int port,
int verbose, ioa_engine_handle e,
ioa_engine_new_connection_event_handler send_socket,
struct relay_server *relay_server);
///////////////////////////////////////////

File diff suppressed because it is too large Load Diff

View File

@ -31,17 +31,17 @@
#ifndef __TURN_ADMIN_SERVER__
#define __TURN_ADMIN_SERVER__
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <event2/bufferevent.h>
#include <event2/buffer.h>
#include <event2/bufferevent.h>
#include "ns_turn_utils.h"
#include "ns_turn_maps.h"
#include "ns_turn_server.h"
#include "ns_turn_utils.h"
#include "apputils.h"
@ -54,25 +54,25 @@ extern "C" {
#define ADMIN_USER_MAX_LENGTH (32)
struct admin_session {
int as_ok;
char as_login[ADMIN_USER_MAX_LENGTH + 1];
char as_realm[STUN_MAX_REALM_SIZE + 1];
char as_eff_realm[STUN_MAX_REALM_SIZE + 1];
size_t number_of_user_sessions;
int as_ok;
char as_login[ADMIN_USER_MAX_LENGTH + 1];
char as_realm[STUN_MAX_REALM_SIZE + 1];
char as_eff_realm[STUN_MAX_REALM_SIZE + 1];
size_t number_of_user_sessions;
};
struct admin_server {
evutil_socket_t listen_fd;
struct event_base* event_base;
ioa_engine_handle e;
int verbose;
struct evconnlistener *l;
struct bufferevent *in_buf;
struct bufferevent *out_buf;
struct bufferevent *https_in_buf;
struct bufferevent *https_out_buf;
ur_map *sessions;
pthread_t thr;
evutil_socket_t listen_fd;
struct event_base *event_base;
ioa_engine_handle e;
int verbose;
struct evconnlistener *l;
struct bufferevent *in_buf;
struct bufferevent *out_buf;
struct bufferevent *https_in_buf;
struct bufferevent *https_out_buf;
ur_map *sessions;
pthread_t thr;
};
///////////////////////////////////////////
@ -94,11 +94,10 @@ extern char cli_password[CLI_PASSWORD_LENGTH];
#define DEFAULT_CLI_MAX_OUTPUT_SESSIONS (256)
extern int cli_max_output_sessions;
extern int use_web_admin;
#define WEB_ADMIN_DEFAULT_IP ("127.0.0.1")
extern ioa_addr web_admin_addr;
extern ioa_addr web_admin_addr;
extern int web_admin_addr_set;
#define WEB_ADMIN_DEFAULT_PORT (8080)
@ -111,7 +110,7 @@ void setup_admin_thread(void);
void admin_server_receive_message(struct bufferevent *bev, void *ptr);
void https_admin_server_receive_message(struct bufferevent *bev, void *ptr);
int send_turn_session_info(struct turn_session_info* tsi);
int send_turn_session_info(struct turn_session_info *tsi);
void send_https_socket(ioa_socket_handle s);
////////////////////////////////////////////
@ -122,4 +121,3 @@ void send_https_socket(ioa_socket_handle s);
#endif
/// __TURN_ADMIN_SERVER__///

View File

@ -31,14 +31,14 @@
#include "ns_turn_maps.h"
#include "ns_turn_msg_defs.h"
#include "ns_turn_ioalib.h"
#include "ns_ioalib_impl.h"
#include "ns_turn_ioalib.h"
#include "turn_ports.h"
////////// DATA ////////////////////////////////////////////
#define PORTS_SIZE (0xFFFF+1)
#define PORTS_SIZE (0xFFFF + 1)
#define TPS_OUT_OF_RANGE ((uint32_t)(-1))
#define TPS_TAKEN_SINGLE ((uint32_t)(-2))
#define TPS_TAKEN_EVEN ((uint32_t)(-3))
@ -57,75 +57,75 @@ typedef struct _turnports turnports;
/////////////// TURNPORTS statics //////////////////////////
static turnports* turnports_create(super_memory_t *sm, uint16_t start, uint16_t end);
static uint16_t turnports_size(turnports* tp);
static turnports *turnports_create(super_memory_t *sm, uint16_t start, uint16_t end);
static uint16_t turnports_size(turnports *tp);
static int turnports_allocate(turnports* tp);
static int turnports_allocate_even(turnports* tp, int allocate_rtcp, uint64_t *reservation_token);
static int turnports_allocate(turnports *tp);
static int turnports_allocate_even(turnports *tp, int allocate_rtcp, uint64_t *reservation_token);
static void turnports_release(turnports* tp, uint16_t port);
static void turnports_release(turnports *tp, uint16_t port);
static int turnports_is_allocated(turnports* tp, uint16_t port);
static int turnports_is_available(turnports* tp, uint16_t port);
static int turnports_is_allocated(turnports *tp, uint16_t port);
static int turnports_is_available(turnports *tp, uint16_t port);
/////////////// UTILS //////////////////////////////////////
static int is_taken(uint32_t status) {
int ret = -1;
switch (status) {
case TPS_TAKEN_SINGLE :
case TPS_TAKEN_EVEN :
case TPS_TAKEN_ODD :
ret = 1;
break;
default:
ret = 0;
};
return ret;
int ret = -1;
switch (status) {
case TPS_TAKEN_SINGLE:
case TPS_TAKEN_EVEN:
case TPS_TAKEN_ODD:
ret = 1;
break;
default:
ret = 0;
};
return ret;
}
static void turnports_randomize(turnports* tp) {
if(tp) {
unsigned int size=(unsigned int)(tp->high-tp->low);
unsigned int i=0;
unsigned int cycles=size*10;
for(i=0;i<cycles;i++) {
uint16_t port1 = (uint16_t)(tp->low + (uint16_t)(((unsigned long)turn_random())%((unsigned long)size)));
uint16_t port2 = (uint16_t)(tp->low + (uint16_t)(((unsigned long)turn_random())%((unsigned long)size)));
if(port1!=port2) {
int pos1=tp->status[port1];
int pos2=tp->status[port2];
int tmp=(int)tp->status[port1];
tp->status[port1]=tp->status[port2];
tp->status[port2]=(uint32_t)tmp;
tmp=(int)tp->ports[pos1];
tp->ports[pos1]=tp->ports[pos2];
tp->ports[pos2]=(uint16_t)tmp;
static void turnports_randomize(turnports *tp) {
if (tp) {
unsigned int size = (unsigned int)(tp->high - tp->low);
unsigned int i = 0;
unsigned int cycles = size * 10;
for (i = 0; i < cycles; i++) {
uint16_t port1 = (uint16_t)(tp->low + (uint16_t)(((unsigned long)turn_random()) % ((unsigned long)size)));
uint16_t port2 = (uint16_t)(tp->low + (uint16_t)(((unsigned long)turn_random()) % ((unsigned long)size)));
if (port1 != port2) {
int pos1 = tp->status[port1];
int pos2 = tp->status[port2];
int tmp = (int)tp->status[port1];
tp->status[port1] = tp->status[port2];
tp->status[port2] = (uint32_t)tmp;
tmp = (int)tp->ports[pos1];
tp->ports[pos1] = tp->ports[pos2];
tp->ports[pos2] = (uint16_t)tmp;
}
}
}
}
}
static void turnports_init(turnports* tp, uint16_t start, uint16_t end) {
static void turnports_init(turnports *tp, uint16_t start, uint16_t end) {
tp->low=start;
tp->high=((uint32_t)end)+1;
tp->low = start;
tp->high = ((uint32_t)end) + 1;
tp->range_start=start;
tp->range_stop=end;
int i=0;
for(i=0;i<start;i++) {
tp->status[i]=TPS_OUT_OF_RANGE;
tp->ports[i]=(uint16_t)i;
tp->range_start = start;
tp->range_stop = end;
int i = 0;
for (i = 0; i < start; i++) {
tp->status[i] = TPS_OUT_OF_RANGE;
tp->ports[i] = (uint16_t)i;
}
for(i=start;i<=end;i++) {
tp->status[i]=(uint32_t)i;
tp->ports[i]=(uint16_t)i;
for (i = start; i <= end; i++) {
tp->status[i] = (uint32_t)i;
tp->ports[i] = (uint16_t)i;
}
for(i=((int)end)+1;i<PORTS_SIZE;i++) {
tp->status[i]=TPS_OUT_OF_RANGE;
tp->ports[i]=(uint16_t)i;
for (i = ((int)end) + 1; i < PORTS_SIZE; i++) {
tp->status[i] = TPS_OUT_OF_RANGE;
tp->ports[i] = (uint16_t)i;
}
turnports_randomize(tp);
@ -135,57 +135,59 @@ static void turnports_init(turnports* tp, uint16_t start, uint16_t end) {
/////////////// FUNC ///////////////////////////////////////
turnports* turnports_create(super_memory_t *sm, uint16_t start, uint16_t end) {
turnports *turnports_create(super_memory_t *sm, uint16_t start, uint16_t end) {
if(start>end) return NULL;
if (start > end)
return NULL;
turnports* ret=(turnports*)allocate_super_memory_region(sm, sizeof(turnports));
turnports_init(ret,start,end);
turnports *ret = (turnports *)allocate_super_memory_region(sm, sizeof(turnports));
turnports_init(ret, start, end);
return ret;
}
uint16_t turnports_size(turnports* tp) {
if(!tp) return 0;
uint16_t turnports_size(turnports *tp) {
if (!tp)
return 0;
else {
TURN_MUTEX_LOCK(&tp->mutex);
uint16_t ret = (uint16_t)((tp->high-tp->low));
uint16_t ret = (uint16_t)((tp->high - tp->low));
TURN_MUTEX_UNLOCK(&tp->mutex);
return ret;
}
}
int turnports_allocate(turnports* tp) {
int turnports_allocate(turnports *tp) {
int port=-1;
int port = -1;
TURN_MUTEX_LOCK(&tp->mutex);
if(tp) {
if (tp) {
while(1) {
if(tp->high <= tp->low) {
TURN_MUTEX_UNLOCK(&tp->mutex);
return -1;
while (1) {
if (tp->high <= tp->low) {
TURN_MUTEX_UNLOCK(&tp->mutex);
return -1;
}
int position=(uint16_t)(tp->low & 0x0000FFFF);
port=(int)tp->ports[position];
if(port<(int)(tp->range_start) || port>((int)(tp->range_stop))) {
TURN_MUTEX_UNLOCK(&tp->mutex);
return -1;
int position = (uint16_t)(tp->low & 0x0000FFFF);
port = (int)tp->ports[position];
if (port < (int)(tp->range_start) || port > ((int)(tp->range_stop))) {
TURN_MUTEX_UNLOCK(&tp->mutex);
return -1;
}
if(is_taken(tp->status[port])) {
++(tp->low);
continue;
}
if(tp->status[port]!=tp->low) {
++(tp->low);
continue;
if (is_taken(tp->status[port])) {
++(tp->low);
continue;
}
tp->status[port]=TPS_TAKEN_SINGLE;
if (tp->status[port] != tp->low) {
++(tp->low);
continue;
}
tp->status[port] = TPS_TAKEN_SINGLE;
++(tp->low);
break;
}
@ -196,54 +198,54 @@ int turnports_allocate(turnports* tp) {
return port;
}
void turnports_release(turnports* tp, uint16_t port) {
void turnports_release(turnports *tp, uint16_t port) {
TURN_MUTEX_LOCK(&tp->mutex);
if(tp && port>=tp->range_start && port<=tp->range_stop) {
uint16_t position=(uint16_t)(tp->high & 0x0000FFFF);
if(is_taken(tp->status[port])) {
tp->status[port]=tp->high;
tp->ports[position]=port;
if (tp && port >= tp->range_start && port <= tp->range_stop) {
uint16_t position = (uint16_t)(tp->high & 0x0000FFFF);
if (is_taken(tp->status[port])) {
tp->status[port] = tp->high;
tp->ports[position] = port;
++(tp->high);
}
}
TURN_MUTEX_UNLOCK(&tp->mutex);
}
int turnports_allocate_even(turnports* tp, int allocate_rtcp, uint64_t *reservation_token) {
if(tp) {
int turnports_allocate_even(turnports *tp, int allocate_rtcp, uint64_t *reservation_token) {
if (tp) {
TURN_MUTEX_LOCK(&tp->mutex);
uint16_t size = turnports_size(tp);
if(size>1) {
uint16_t i=0;
for(i=0;i<size;i++) {
int port=turnports_allocate(tp);
if(port & 0x00000001) {
turnports_release(tp,port);
} else {
if(!allocate_rtcp) {
TURN_MUTEX_UNLOCK(&tp->mutex);
return port;
} else {
int rtcp_port=port+1;
if(rtcp_port>tp->range_stop) {
turnports_release(tp,port);
} else if(!turnports_is_available(tp,rtcp_port)) {
turnports_release(tp,port);
} else {
tp->status[port]=TPS_TAKEN_EVEN;
tp->status[rtcp_port]=TPS_TAKEN_ODD;
if(reservation_token) {
uint16_t *v16=(uint16_t*)reservation_token;
uint32_t *v32=(uint32_t*)reservation_token;
v16[0]=(uint16_t)(tp->ports[(uint16_t)(tp->low & 0x0000FFFF)]);
v16[1]=(uint16_t)(tp->ports[(uint16_t)(tp->high & 0x0000FFFF)]);
v32[1]=(uint32_t)turn_random();
}
TURN_MUTEX_UNLOCK(&tp->mutex);
return port;
}
}
}
if (size > 1) {
uint16_t i = 0;
for (i = 0; i < size; i++) {
int port = turnports_allocate(tp);
if (port & 0x00000001) {
turnports_release(tp, port);
} else {
if (!allocate_rtcp) {
TURN_MUTEX_UNLOCK(&tp->mutex);
return port;
} else {
int rtcp_port = port + 1;
if (rtcp_port > tp->range_stop) {
turnports_release(tp, port);
} else if (!turnports_is_available(tp, rtcp_port)) {
turnports_release(tp, port);
} else {
tp->status[port] = TPS_TAKEN_EVEN;
tp->status[rtcp_port] = TPS_TAKEN_ODD;
if (reservation_token) {
uint16_t *v16 = (uint16_t *)reservation_token;
uint32_t *v32 = (uint32_t *)reservation_token;
v16[0] = (uint16_t)(tp->ports[(uint16_t)(tp->low & 0x0000FFFF)]);
v16[1] = (uint16_t)(tp->ports[(uint16_t)(tp->high & 0x0000FFFF)]);
v32[1] = (uint32_t)turn_random();
}
TURN_MUTEX_UNLOCK(&tp->mutex);
return port;
}
}
}
}
}
TURN_MUTEX_UNLOCK(&tp->mutex);
@ -251,8 +253,9 @@ int turnports_allocate_even(turnports* tp, int allocate_rtcp, uint64_t *reservat
return -1;
}
int turnports_is_allocated(turnports* tp, uint16_t port) {
if(!tp) return 0;
int turnports_is_allocated(turnports *tp, uint16_t port) {
if (!tp)
return 0;
else {
TURN_MUTEX_LOCK(&tp->mutex);
int ret = is_taken(tp->status[port]);
@ -261,15 +264,15 @@ int turnports_is_allocated(turnports* tp, uint16_t port) {
}
}
int turnports_is_available(turnports* tp, uint16_t port) {
if(tp) {
int turnports_is_available(turnports *tp, uint16_t port) {
if (tp) {
TURN_MUTEX_LOCK(&tp->mutex);
uint32_t status = tp->status[port];
if((status!=TPS_OUT_OF_RANGE) && !is_taken(status)) {
uint16_t position=(uint16_t)(status & 0x0000FFFF);
if(tp->ports[position]==port) {
TURN_MUTEX_UNLOCK(&tp->mutex);
return 1;
if ((status != TPS_OUT_OF_RANGE) && !is_taken(status)) {
uint16_t position = (uint16_t)(status & 0x0000FFFF);
if (tp->ports[position] == port) {
TURN_MUTEX_UNLOCK(&tp->mutex);
return 1;
}
}
TURN_MUTEX_UNLOCK(&tp->mutex);
@ -279,139 +282,127 @@ int turnports_is_available(turnports* tp, uint16_t port) {
/////////////////// IP-mapped PORTS /////////////////////////////////////
struct _turnipports
{
super_memory_t *sm;
uint16_t start;
uint16_t end;
ur_addr_map ip_to_turnports_udp;
ur_addr_map ip_to_turnports_tcp;
TURN_MUTEX_DECLARE(mutex)
struct _turnipports {
super_memory_t *sm;
uint16_t start;
uint16_t end;
ur_addr_map ip_to_turnports_udp;
ur_addr_map ip_to_turnports_tcp;
TURN_MUTEX_DECLARE(mutex)
};
//////////////////////////////////////////////////
static ur_addr_map *get_map(turnipports *tp, uint8_t transport)
{
if(transport == STUN_ATTRIBUTE_TRANSPORT_TCP_VALUE)
return &(tp->ip_to_turnports_tcp);
return &(tp->ip_to_turnports_udp);
static ur_addr_map *get_map(turnipports *tp, uint8_t transport) {
if (transport == STUN_ATTRIBUTE_TRANSPORT_TCP_VALUE)
return &(tp->ip_to_turnports_tcp);
return &(tp->ip_to_turnports_udp);
}
//////////////////////////////////////////////////
static turnipports* turnipports_singleton = NULL;
static turnipports *turnipports_singleton = NULL;
turnipports* turnipports_create(super_memory_t *sm, uint16_t start, uint16_t end)
{
turnipports *ret = (turnipports*) allocate_super_memory_region(sm, sizeof(turnipports));
ret->sm = sm;
ur_addr_map_init(&(ret->ip_to_turnports_udp));
ur_addr_map_init(&(ret->ip_to_turnports_tcp));
ret->start = start;
ret->end = end;
TURN_MUTEX_INIT_RECURSIVE(&(ret->mutex));
turnipports_singleton = ret;
return ret;
turnipports *turnipports_create(super_memory_t *sm, uint16_t start, uint16_t end) {
turnipports *ret = (turnipports *)allocate_super_memory_region(sm, sizeof(turnipports));
ret->sm = sm;
ur_addr_map_init(&(ret->ip_to_turnports_udp));
ur_addr_map_init(&(ret->ip_to_turnports_tcp));
ret->start = start;
ret->end = end;
TURN_MUTEX_INIT_RECURSIVE(&(ret->mutex));
turnipports_singleton = ret;
return ret;
}
static turnports* turnipports_add(turnipports* tp, uint8_t transport, const ioa_addr *backend_addr)
{
ur_addr_map_value_type t = 0;
if (tp && backend_addr) {
ioa_addr ba;
addr_cpy(&ba, backend_addr);
addr_set_port(&ba, 0);
TURN_MUTEX_LOCK((const turn_mutex*)&(tp->mutex));
if (!ur_addr_map_get(get_map(tp, transport), &ba, &t)) {
t = (ur_addr_map_value_type) turnports_create(tp->sm, tp->start, tp->end);
ur_addr_map_put(get_map(tp, transport), &ba, t);
}
TURN_MUTEX_UNLOCK((const turn_mutex*)&(tp->mutex));
}
return (turnports*) t;
static turnports *turnipports_add(turnipports *tp, uint8_t transport, const ioa_addr *backend_addr) {
ur_addr_map_value_type t = 0;
if (tp && backend_addr) {
ioa_addr ba;
addr_cpy(&ba, backend_addr);
addr_set_port(&ba, 0);
TURN_MUTEX_LOCK((const turn_mutex *)&(tp->mutex));
if (!ur_addr_map_get(get_map(tp, transport), &ba, &t)) {
t = (ur_addr_map_value_type)turnports_create(tp->sm, tp->start, tp->end);
ur_addr_map_put(get_map(tp, transport), &ba, t);
}
TURN_MUTEX_UNLOCK((const turn_mutex *)&(tp->mutex));
}
return (turnports *)t;
}
void turnipports_add_ip(uint8_t transport, const ioa_addr *backend_addr)
{
turnipports_add(turnipports_singleton, transport, backend_addr);
void turnipports_add_ip(uint8_t transport, const ioa_addr *backend_addr) {
turnipports_add(turnipports_singleton, transport, backend_addr);
}
int turnipports_allocate(turnipports* tp, uint8_t transport, const ioa_addr *backend_addr)
{
int ret = -1;
if (tp && backend_addr) {
TURN_MUTEX_LOCK((const turn_mutex*)&(tp->mutex));
turnports *t = turnipports_add(tp, transport, backend_addr);
ret = turnports_allocate(t);
TURN_MUTEX_UNLOCK((const turn_mutex*)&(tp->mutex));
}
return ret;
int turnipports_allocate(turnipports *tp, uint8_t transport, const ioa_addr *backend_addr) {
int ret = -1;
if (tp && backend_addr) {
TURN_MUTEX_LOCK((const turn_mutex *)&(tp->mutex));
turnports *t = turnipports_add(tp, transport, backend_addr);
ret = turnports_allocate(t);
TURN_MUTEX_UNLOCK((const turn_mutex *)&(tp->mutex));
}
return ret;
}
int turnipports_allocate_even(turnipports* tp, const ioa_addr *backend_addr, int allocate_rtcp,
uint64_t *reservation_token)
{
int ret = -1;
if (tp && backend_addr) {
TURN_MUTEX_LOCK((const turn_mutex*)&(tp->mutex));
turnports *t = turnipports_add(tp, STUN_ATTRIBUTE_TRANSPORT_UDP_VALUE, backend_addr);
ret = turnports_allocate_even(t, allocate_rtcp, reservation_token);
TURN_MUTEX_UNLOCK((const turn_mutex*)&(tp->mutex));
}
return ret;
int turnipports_allocate_even(turnipports *tp, const ioa_addr *backend_addr, int allocate_rtcp,
uint64_t *reservation_token) {
int ret = -1;
if (tp && backend_addr) {
TURN_MUTEX_LOCK((const turn_mutex *)&(tp->mutex));
turnports *t = turnipports_add(tp, STUN_ATTRIBUTE_TRANSPORT_UDP_VALUE, backend_addr);
ret = turnports_allocate_even(t, allocate_rtcp, reservation_token);
TURN_MUTEX_UNLOCK((const turn_mutex *)&(tp->mutex));
}
return ret;
}
void turnipports_release(turnipports* tp, uint8_t transport, const ioa_addr *socket_addr)
{
if (tp && socket_addr) {
ioa_addr ba;
ur_addr_map_value_type t;
addr_cpy(&ba, socket_addr);
addr_set_port(&ba, 0);
TURN_MUTEX_LOCK((const turn_mutex*)&(tp->mutex));
if (ur_addr_map_get(get_map(tp, transport), &ba, &t)) {
turnports_release((turnports*) t, addr_get_port(socket_addr));
}
TURN_MUTEX_UNLOCK((const turn_mutex*)&(tp->mutex));
}
void turnipports_release(turnipports *tp, uint8_t transport, const ioa_addr *socket_addr) {
if (tp && socket_addr) {
ioa_addr ba;
ur_addr_map_value_type t;
addr_cpy(&ba, socket_addr);
addr_set_port(&ba, 0);
TURN_MUTEX_LOCK((const turn_mutex *)&(tp->mutex));
if (ur_addr_map_get(get_map(tp, transport), &ba, &t)) {
turnports_release((turnports *)t, addr_get_port(socket_addr));
}
TURN_MUTEX_UNLOCK((const turn_mutex *)&(tp->mutex));
}
}
int turnipports_is_allocated(turnipports* tp, uint8_t transport, const ioa_addr *backend_addr, uint16_t port)
{
int ret = 0;
if (tp && backend_addr) {
ioa_addr ba;
ur_addr_map_value_type t;
addr_cpy(&ba, backend_addr);
addr_set_port(&ba, 0);
TURN_MUTEX_LOCK((const turn_mutex*)&(tp->mutex));
if (ur_addr_map_get(get_map(tp,transport), &ba, &t)) {
ret = turnports_is_allocated((turnports*) t, port);
}
TURN_MUTEX_UNLOCK((const turn_mutex*)&(tp->mutex));
}
return ret;
int turnipports_is_allocated(turnipports *tp, uint8_t transport, const ioa_addr *backend_addr, uint16_t port) {
int ret = 0;
if (tp && backend_addr) {
ioa_addr ba;
ur_addr_map_value_type t;
addr_cpy(&ba, backend_addr);
addr_set_port(&ba, 0);
TURN_MUTEX_LOCK((const turn_mutex *)&(tp->mutex));
if (ur_addr_map_get(get_map(tp, transport), &ba, &t)) {
ret = turnports_is_allocated((turnports *)t, port);
}
TURN_MUTEX_UNLOCK((const turn_mutex *)&(tp->mutex));
}
return ret;
}
int turnipports_is_available(turnipports* tp, uint8_t transport, const ioa_addr *backend_addr, uint16_t port)
{
int ret = 0;
if (tp && backend_addr) {
ioa_addr ba;
ur_addr_map_value_type t;
addr_cpy(&ba, backend_addr);
addr_set_port(&ba, 0);
TURN_MUTEX_LOCK((const turn_mutex*)&(tp->mutex));
if (!ur_addr_map_get(get_map(tp,transport), &ba, &t)) {
ret = 1;
} else {
ret = turnports_is_available((turnports*) t, port);
}
TURN_MUTEX_UNLOCK((const turn_mutex*)&(tp->mutex));
}
return ret;
int turnipports_is_available(turnipports *tp, uint8_t transport, const ioa_addr *backend_addr, uint16_t port) {
int ret = 0;
if (tp && backend_addr) {
ioa_addr ba;
ur_addr_map_value_type t;
addr_cpy(&ba, backend_addr);
addr_set_port(&ba, 0);
TURN_MUTEX_LOCK((const turn_mutex *)&(tp->mutex));
if (!ur_addr_map_get(get_map(tp, transport), &ba, &t)) {
ret = 1;
} else {
ret = turnports_is_available((turnports *)t, port);
}
TURN_MUTEX_UNLOCK((const turn_mutex *)&(tp->mutex));
}
return ret;
}
//////////////////////////////////////////////////////////////////

View File

@ -51,18 +51,18 @@ typedef struct _turnipports turnipports;
//////////////////////////////////////////////////
turnipports* turnipports_create(super_memory_t *sm, uint16_t start, uint16_t end);
turnipports *turnipports_create(super_memory_t *sm, uint16_t start, uint16_t end);
void turnipports_add_ip(uint8_t transport, const ioa_addr *backend_addr);
int turnipports_allocate(turnipports* tp, uint8_t transport, const ioa_addr *backend_addr);
int turnipports_allocate_even(turnipports* tp, const ioa_addr *backend_addr,
int allocate_rtcp, uint64_t *reservation_token);
int turnipports_allocate(turnipports *tp, uint8_t transport, const ioa_addr *backend_addr);
int turnipports_allocate_even(turnipports *tp, const ioa_addr *backend_addr, int allocate_rtcp,
uint64_t *reservation_token);
void turnipports_release(turnipports* tp, uint8_t transport, const ioa_addr *socket_addr);
void turnipports_release(turnipports *tp, uint8_t transport, const ioa_addr *socket_addr);
int turnipports_is_allocated(turnipports* tp, uint8_t transport, const ioa_addr *backend_addr, uint16_t port);
int turnipports_is_available(turnipports* tp, uint8_t transport, const ioa_addr *backend_addr, uint16_t port);
int turnipports_is_allocated(turnipports *tp, uint8_t transport, const ioa_addr *backend_addr, uint16_t port);
int turnipports_is_available(turnipports *tp, uint8_t transport, const ioa_addr *backend_addr, uint16_t port);
//////////////////////////////////////////////////

File diff suppressed because it is too large Load Diff

View File

@ -31,14 +31,14 @@
#ifndef __USERDB__
#define __USERDB__
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#include "hiredis_libevent2.h"
#include "ns_turn_utils.h"
#include "ns_turn_maps.h"
#include "ns_turn_server.h"
#include "ns_turn_utils.h"
#include "apputils.h"
@ -56,78 +56,80 @@ typedef struct _realm_params_t realm_params_t;
struct _realm_status_t {
vint total_current_allocs;
ur_string_map *alloc_counters;
vint total_current_allocs;
ur_string_map *alloc_counters;
};
struct _realm_params_t {
int is_default_realm;
int is_default_realm;
realm_options_t options;
realm_status_t status;
realm_options_t options;
realm_status_t status;
};
void lock_realms(void);
void unlock_realms(void);
void update_o_to_realm(ur_string_map * o_to_realm_new);
void update_o_to_realm(ur_string_map *o_to_realm_new);
//////////// USER DB //////////////////////////////
struct auth_message {
turnserver_id id;
turn_credential_type ct;
int in_oauth;
int out_oauth;
int max_session_time;
uint8_t username[STUN_MAX_USERNAME_SIZE + 1];
uint8_t realm[STUN_MAX_REALM_SIZE + 1];
hmackey_t key;
password_t pwd;
get_username_resume_cb resume_func;
ioa_net_data in_buffer;
uint64_t ctxkey;
int success;
turnserver_id id;
turn_credential_type ct;
int in_oauth;
int out_oauth;
int max_session_time;
uint8_t username[STUN_MAX_USERNAME_SIZE + 1];
uint8_t realm[STUN_MAX_REALM_SIZE + 1];
hmackey_t key;
password_t pwd;
get_username_resume_cb resume_func;
ioa_net_data in_buffer;
uint64_t ctxkey;
int success;
};
enum _TURN_USERDB_TYPE {
#if !defined(TURN_NO_SQLITE)
TURN_USERDB_TYPE_UNKNOWN=-1,
TURN_USERDB_TYPE_SQLITE=0
TURN_USERDB_TYPE_UNKNOWN = -1,
TURN_USERDB_TYPE_SQLITE = 0
#else
TURN_USERDB_TYPE_UNKNOWN=0
TURN_USERDB_TYPE_UNKNOWN = 0
#endif
#if !defined(TURN_NO_PQ)
,TURN_USERDB_TYPE_PQ
,
TURN_USERDB_TYPE_PQ
#endif
#if !defined(TURN_NO_MYSQL)
,TURN_USERDB_TYPE_MYSQL
,
TURN_USERDB_TYPE_MYSQL
#endif
#if !defined(TURN_NO_MONGO)
,TURN_USERDB_TYPE_MONGO
,
TURN_USERDB_TYPE_MONGO
#endif
,TURN_USERDB_TYPE_REDIS
,
TURN_USERDB_TYPE_REDIS
};
typedef enum _TURN_USERDB_TYPE TURN_USERDB_TYPE;
enum _TURNADMIN_COMMAND_TYPE {
TA_COMMAND_UNKNOWN,
TA_PRINT_KEY,
TA_UPDATE_USER,
TA_DELETE_USER,
TA_LIST_USERS,
TA_SET_SECRET,
TA_SHOW_SECRET,
TA_DEL_SECRET,
TA_ADD_ORIGIN,
TA_DEL_ORIGIN,
TA_LIST_ORIGINS,
TA_SET_REALM_OPTION,
TA_LIST_REALM_OPTIONS
TA_COMMAND_UNKNOWN,
TA_PRINT_KEY,
TA_UPDATE_USER,
TA_DELETE_USER,
TA_LIST_USERS,
TA_SET_SECRET,
TA_SHOW_SECRET,
TA_DEL_SECRET,
TA_ADD_ORIGIN,
TA_DEL_ORIGIN,
TA_LIST_ORIGINS,
TA_SET_REALM_OPTION,
TA_LIST_REALM_OPTIONS
};
typedef enum _TURNADMIN_COMMAND_TYPE TURNADMIN_COMMAND_TYPE;
@ -135,8 +137,8 @@ typedef enum _TURNADMIN_COMMAND_TYPE TURNADMIN_COMMAND_TYPE;
/////////// SHARED SECRETS //////////////////
struct _secrets_list {
char **secrets;
size_t sz;
char **secrets;
size_t sz;
};
typedef struct _secrets_list secrets_list_t;
@ -145,34 +147,33 @@ typedef struct _secrets_list secrets_list_t;
#define TURN_LONG_STRING_SIZE (1025)
typedef struct _redis_stats_db_t {
char connection_string[TURN_LONG_STRING_SIZE];
char connection_string_sanitized[TURN_LONG_STRING_SIZE];
char connection_string[TURN_LONG_STRING_SIZE];
char connection_string_sanitized[TURN_LONG_STRING_SIZE];
} redis_stats_db_t;
typedef struct _ram_users_db_t {
size_t users_number;
ur_string_map *static_accounts;
secrets_list_t static_auth_secrets;
size_t users_number;
ur_string_map *static_accounts;
secrets_list_t static_auth_secrets;
} ram_users_db_t;
typedef struct _persistent_users_db_t {
char userdb[TURN_LONG_STRING_SIZE];
char userdb_sanitized[TURN_LONG_STRING_SIZE];
char userdb[TURN_LONG_STRING_SIZE];
char userdb_sanitized[TURN_LONG_STRING_SIZE];
} persistent_users_db_t;
typedef struct _default_users_db_t
{
TURN_USERDB_TYPE userdb_type;
typedef struct _default_users_db_t {
TURN_USERDB_TYPE userdb_type;
persistent_users_db_t persistent_users_db;
persistent_users_db_t persistent_users_db;
ram_users_db_t ram_db;
ram_users_db_t ram_db;
} default_users_db_t;
/////////////////////////////////////////////
realm_params_t* get_realm(char* name);
realm_params_t *get_realm(char *name);
void set_default_realm_name(char *realm);
int change_total_quota(char *realm, int value);
int change_user_quota(char *realm, int value);
@ -184,36 +185,41 @@ void init_dynamic_ip_lists(void);
void update_white_and_black_lists(void);
void clean_secrets_list(secrets_list_t *sl);
size_t get_secrets_list_size(secrets_list_t *sl);
const char* get_secrets_list_elem(secrets_list_t *sl, size_t i);
void add_to_secrets_list(secrets_list_t *sl, const char* elem);
const char *get_secrets_list_elem(secrets_list_t *sl, size_t i);
void add_to_secrets_list(secrets_list_t *sl, const char *elem);
/////////// USER DB CHECK //////////////////
int get_user_key(int in_oauth, int *out_oauth, int *max_session_time, uint8_t *uname, uint8_t *realm, hmackey_t key, ioa_network_buffer_handle nbh);
uint8_t *start_user_check(turnserver_id id, turn_credential_type ct, int in_oauth, int *out_oauth, uint8_t *uname, uint8_t *realm, get_username_resume_cb resume, ioa_net_data *in_buffer, uint64_t ctxkey, int *postpone_reply);
int get_user_key(int in_oauth, int *out_oauth, int *max_session_time, uint8_t *uname, uint8_t *realm, hmackey_t key,
ioa_network_buffer_handle nbh);
uint8_t *start_user_check(turnserver_id id, turn_credential_type ct, int in_oauth, int *out_oauth, uint8_t *uname,
uint8_t *realm, get_username_resume_cb resume, ioa_net_data *in_buffer, uint64_t ctxkey,
int *postpone_reply);
int check_new_allocation_quota(uint8_t *username, int oauth, uint8_t *realm);
void release_allocation_quota(uint8_t *username, int oauth, uint8_t *realm);
/////////// Handle user DB /////////////////
#if defined(DB_TEST)
void run_db_test(void);
void run_db_test(void);
#endif
void auth_ping(redis_context_handle rch);
void reread_realms(void);
int add_static_user_account(char *user);
int adminuser(uint8_t *user, uint8_t *realm, uint8_t *pwd, uint8_t *secret, uint8_t *origin, TURNADMIN_COMMAND_TYPE ct, perf_options_t* po, int is_admin);
int adminuser(uint8_t *user, uint8_t *realm, uint8_t *pwd, uint8_t *secret, uint8_t *origin, TURNADMIN_COMMAND_TYPE ct,
perf_options_t *po, int is_admin);
int add_ip_list_range(const char* range, const char* realm, ip_range_list_t * list);
int check_ip_list_range(const char* range);
ip_range_list_t* get_ip_list(const char *kind);
int add_ip_list_range(const char *range, const char *realm, ip_range_list_t *list);
int check_ip_list_range(const char *range);
ip_range_list_t *get_ip_list(const char *kind);
void ip_list_free(ip_range_list_t *l);
///////////// Redis //////////////////////
#if !defined(TURN_NO_HIREDIS)
redis_context_handle get_redis_async_connection(struct event_base *base, redis_stats_db_t* redis_stats_db, int delete_keys);
redis_context_handle get_redis_async_connection(struct event_base *base, redis_stats_db_t *redis_stats_db,
int delete_keys);
#endif
////////////////////////////////////////////
@ -224,4 +230,3 @@ redis_context_handle get_redis_async_connection(struct event_base *base, redis_s
#endif
/// __USERDB__///

View File

@ -28,8 +28,8 @@
* SUCH DAMAGE.
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
@ -39,540 +39,527 @@
#include <unistd.h>
#endif
#include "ns_turn_utils.h"
#include "apputils.h"
#include "ns_turn_utils.h"
#include "stun_buffer.h"
//////////// OAUTH //////////////////
static const char* encs[]={
static const char *encs[] = {
#if !defined(TURN_NO_GCM)
"A128GCM", "A256GCM",
"A128GCM", "A256GCM",
#endif
NULL};
NULL};
static int print_extra = 0;
void print_field5769(const char* name, const void* f0, size_t len);
void print_field5769(const char* name, const void* f0, size_t len) {
const unsigned char* f = (const unsigned char*)f0;
printf("\nfield %s %lu==>>\n",name,(unsigned long)len);
void print_field5769(const char *name, const void *f0, size_t len);
void print_field5769(const char *name, const void *f0, size_t len) {
const unsigned char *f = (const unsigned char *)f0;
printf("\nfield %s %lu==>>\n", name, (unsigned long)len);
size_t i;
for(i = 0;i<len;++i) {
printf("\\x%02x",(unsigned int)f[i]);
for (i = 0; i < len; ++i) {
printf("\\x%02x", (unsigned int)f[i]);
}
printf("\n<<==field %s\n",name);
printf("\n<<==field %s\n", name);
}
static int check_oauth(void) {
const char server_name[33] = "blackdow.carleon.gov";
const char server_name[33] = "blackdow.carleon.gov";
size_t i_encs;
size_t i_encs;
const char long_term_key[33] = "HGkj32KJGiuy098sdfaqbNjOiaz71923";
const char long_term_key[33] = "HGkj32KJGiuy098sdfaqbNjOiaz71923";
size_t ltp_output_length=0;
size_t ltp_output_length = 0;
const char* base64encoded_ltp = base64_encode((const unsigned char *)long_term_key,
strlen(long_term_key),
&ltp_output_length);
const char *base64encoded_ltp =
base64_encode((const unsigned char *)long_term_key, strlen(long_term_key), &ltp_output_length);
const char mac_key[33] = "ZksjpweoixXmvn67534m";
const size_t mac_key_length=strlen(mac_key);
const uint64_t token_timestamp = (uint64_t)(92470300704768LL);
const uint32_t token_lifetime = 3600;
const char mac_key[33] = "ZksjpweoixXmvn67534m";
const size_t mac_key_length = strlen(mac_key);
const uint64_t token_timestamp = (uint64_t)(92470300704768LL);
const uint32_t token_lifetime = 3600;
const char kid[33] = "2783466234";
const turn_time_t key_timestamp = 1234567890;
const turn_time_t key_lifetime = 3600;
const char kid[33] = "2783466234";
const turn_time_t key_timestamp = 1234567890;
const turn_time_t key_lifetime = 3600;
const char gcm_nonce[OAUTH_GCM_NONCE_SIZE+1] = "h4j3k2l2n4b5";
const char gcm_nonce[OAUTH_GCM_NONCE_SIZE + 1] = "h4j3k2l2n4b5";
{
{
{
{
for (i_encs = 0; encs[i_encs]; ++i_encs) {
for (i_encs = 0; encs[i_encs]; ++i_encs) {
printf("oauth token %s:",encs[i_encs]);
printf("oauth token %s:", encs[i_encs]);
if(print_extra)
printf("\n");
if (print_extra)
printf("\n");
oauth_token ot;
memset(&ot, 0, sizeof(ot));
ot.enc_block.key_length = (uint16_t)mac_key_length;
STRCPY(ot.enc_block.mac_key,mac_key);
ot.enc_block.timestamp = token_timestamp;
ot.enc_block.lifetime = token_lifetime;
oauth_token ot;
memset(&ot, 0, sizeof(ot));
ot.enc_block.key_length = (uint16_t)mac_key_length;
STRCPY(ot.enc_block.mac_key, mac_key);
ot.enc_block.timestamp = token_timestamp;
ot.enc_block.lifetime = token_lifetime;
oauth_token dot;
memset((&dot), 0, sizeof(dot));
oauth_key key;
memset(&key, 0, sizeof(key));
oauth_token dot;
memset((&dot), 0, sizeof(dot));
oauth_key key;
memset(&key, 0, sizeof(key));
{
oauth_key_data okd;
memset(&okd, 0, sizeof(okd));
{
oauth_key_data okd;
memset(&okd, 0, sizeof(okd));
{
oauth_key_data_raw okdr;
memset(&okdr, 0, sizeof(okdr));
{
oauth_key_data_raw okdr;
memset(&okdr, 0, sizeof(okdr));
STRCPY(okdr.kid,kid);
STRCPY(okdr.ikm_key,base64encoded_ltp);
STRCPY(okdr.as_rs_alg, encs[i_encs]);
okdr.timestamp = key_timestamp;
okdr.lifetime = key_lifetime;
STRCPY(okdr.kid, kid);
STRCPY(okdr.ikm_key, base64encoded_ltp);
STRCPY(okdr.as_rs_alg, encs[i_encs]);
okdr.timestamp = key_timestamp;
okdr.lifetime = key_lifetime;
convert_oauth_key_data_raw(&okdr, &okd);
convert_oauth_key_data_raw(&okdr, &okd);
char err_msg[1025] = "\0";
size_t err_msg_size = sizeof(err_msg) - 1;
char err_msg[1025] = "\0";
size_t err_msg_size = sizeof(err_msg) - 1;
if (convert_oauth_key_data(&okd, &key, err_msg,
err_msg_size) < 0) {
fprintf(stderr, "%s\n", err_msg);
return -1;
}
}
}
if (convert_oauth_key_data(&okd, &key, err_msg, err_msg_size) < 0) {
fprintf(stderr, "%s\n", err_msg);
return -1;
}
}
}
if(print_extra) {
print_field5769("AS-RS",key.as_rs_key,key.as_rs_key_size);
print_field5769("AUTH",key.auth_key,key.auth_key_size);
}
if (print_extra) {
print_field5769("AS-RS", key.as_rs_key, key.as_rs_key_size);
print_field5769("AUTH", key.auth_key, key.auth_key_size);
}
{
encoded_oauth_token etoken;
memset(&etoken, 0, sizeof(etoken));
{
encoded_oauth_token etoken;
memset(&etoken, 0, sizeof(etoken));
if (encode_oauth_token((const uint8_t *) server_name, &etoken,
&key, &ot, (const uint8_t*)gcm_nonce) < 0) {
fprintf(stderr, "%s: cannot encode oauth token\n",
__FUNCTION__);
return -1;
}
if (encode_oauth_token((const uint8_t *)server_name, &etoken, &key, &ot, (const uint8_t *)gcm_nonce) < 0) {
fprintf(stderr, "%s: cannot encode oauth token\n", __FUNCTION__);
return -1;
}
if(print_extra) {
print_field5769("encoded token",etoken.token,etoken.size);
}
if (print_extra) {
print_field5769("encoded token", etoken.token, etoken.size);
}
if (decode_oauth_token((const uint8_t *) server_name, &etoken,
&key, &dot) < 0) {
fprintf(stderr, "%s: cannot decode oauth token\n",
__FUNCTION__);
return -1;
}
}
if (decode_oauth_token((const uint8_t *)server_name, &etoken, &key, &dot) < 0) {
fprintf(stderr, "%s: cannot decode oauth token\n", __FUNCTION__);
return -1;
}
}
if (strcmp((char*) ot.enc_block.mac_key,
(char*) dot.enc_block.mac_key)) {
fprintf(stderr, "%s: wrong mac key: %s, must be %s\n",
__FUNCTION__, (char*) dot.enc_block.mac_key,
(char*) ot.enc_block.mac_key);
return -1;
}
if (strcmp((char *)ot.enc_block.mac_key, (char *)dot.enc_block.mac_key)) {
fprintf(stderr, "%s: wrong mac key: %s, must be %s\n", __FUNCTION__, (char *)dot.enc_block.mac_key,
(char *)ot.enc_block.mac_key);
return -1;
}
if (ot.enc_block.key_length != dot.enc_block.key_length) {
fprintf(stderr, "%s: wrong key length: %d, must be %d\n",
__FUNCTION__, (int) dot.enc_block.key_length,
(int) ot.enc_block.key_length);
return -1;
}
if (ot.enc_block.timestamp != dot.enc_block.timestamp) {
fprintf(stderr, "%s: wrong timestamp: %llu, must be %llu\n",
__FUNCTION__,
(unsigned long long) dot.enc_block.timestamp,
(unsigned long long) ot.enc_block.timestamp);
return -1;
}
if (ot.enc_block.lifetime != dot.enc_block.lifetime) {
fprintf(stderr, "%s: wrong lifetime: %lu, must be %lu\n",
__FUNCTION__,
(unsigned long) dot.enc_block.lifetime,
(unsigned long) ot.enc_block.lifetime);
return -1;
}
if (ot.enc_block.key_length != dot.enc_block.key_length) {
fprintf(stderr, "%s: wrong key length: %d, must be %d\n", __FUNCTION__, (int)dot.enc_block.key_length,
(int)ot.enc_block.key_length);
return -1;
}
if (ot.enc_block.timestamp != dot.enc_block.timestamp) {
fprintf(stderr, "%s: wrong timestamp: %llu, must be %llu\n", __FUNCTION__,
(unsigned long long)dot.enc_block.timestamp, (unsigned long long)ot.enc_block.timestamp);
return -1;
}
if (ot.enc_block.lifetime != dot.enc_block.lifetime) {
fprintf(stderr, "%s: wrong lifetime: %lu, must be %lu\n", __FUNCTION__, (unsigned long)dot.enc_block.lifetime,
(unsigned long)ot.enc_block.lifetime);
return -1;
}
printf("OK\n");
}
}
}
printf("OK\n");
}
}
}
return 0;
return 0;
}
//////////////////////////////////////////////////
static SHATYPE shatype = SHATYPE_SHA1;
int main(int argc, const char **argv)
{
int res = -1;
int main(int argc, const char **argv) {
int res = -1;
UNUSED_ARG(argc);
UNUSED_ARG(argv);
UNUSED_ARG(argc);
UNUSED_ARG(argv);
if(argc>1)
print_extra = 1;
if (argc > 1)
print_extra = 1;
set_logfile("stdout");
set_no_stdout_log(1);
set_system_parameters(0);
set_logfile("stdout");
set_no_stdout_log(1);
set_system_parameters(0);
{
const unsigned char reqstc[] =
"\x00\x01\x00\x58"
"\x21\x12\xa4\x42"
"\xb7\xe7\xa7\x01\xbc\x34\xd6\x86\xfa\x87\xdf\xae"
"\x80\x22\x00\x10"
"STUN test client"
"\x00\x24\x00\x04"
"\x6e\x00\x01\xff"
"\x80\x29\x00\x08"
"\x93\x2f\xf9\xb1\x51\x26\x3b\x36"
"\x00\x06\x00\x09"
"\x65\x76\x74\x6a\x3a\x68\x36\x76\x59\x20\x20\x20"
"\x00\x08\x00\x14"
"\x9a\xea\xa7\x0c\xbf\xd8\xcb\x56\x78\x1e\xf2\xb5"
"\xb2\xd3\xf2\x49\xc1\xb5\x71\xa2"
"\x80\x28\x00\x04"
"\xe5\x7a\x3b\xcf";
{
const unsigned char reqstc[] = "\x00\x01\x00\x58"
"\x21\x12\xa4\x42"
"\xb7\xe7\xa7\x01\xbc\x34\xd6\x86\xfa\x87\xdf\xae"
"\x80\x22\x00\x10"
"STUN test client"
"\x00\x24\x00\x04"
"\x6e\x00\x01\xff"
"\x80\x29\x00\x08"
"\x93\x2f\xf9\xb1\x51\x26\x3b\x36"
"\x00\x06\x00\x09"
"\x65\x76\x74\x6a\x3a\x68\x36\x76\x59\x20\x20\x20"
"\x00\x08\x00\x14"
"\x9a\xea\xa7\x0c\xbf\xd8\xcb\x56\x78\x1e\xf2\xb5"
"\xb2\xd3\xf2\x49\xc1\xb5\x71\xa2"
"\x80\x28\x00\x04"
"\xe5\x7a\x3b\xcf";
uint8_t buf[sizeof(reqstc)];
memcpy(buf, reqstc, sizeof(reqstc));
uint8_t buf[sizeof(reqstc)];
memcpy(buf, reqstc, sizeof(reqstc));
{//fingerprintfs etc
{ // fingerprintfs etc
res = stun_is_command_message_full_check_str(buf, sizeof(reqstc) - 1, 1, NULL);
printf("RFC 5769 message fingerprint test(0) result: ");
res = stun_is_command_message_full_check_str(buf, sizeof(reqstc) - 1, 1, NULL);
printf("RFC 5769 message fingerprint test(0) result: ");
if (res) {
printf("success\n");
} else if (res == 0) {
printf("failure on fingerprint(0) check\n");
exit(-1);
}
}
if (res) {
printf("success\n");
} else if (res == 0) {
printf("failure on fingerprint(0) check\n");
exit(-1);
}
}
{//short-term credentials
uint8_t uname[33];
uint8_t realm[33];
uint8_t upwd[33];
strcpy((char*) upwd, "VOkJxbRl1RmTxUk/WvJxBt");
{ // short-term credentials
uint8_t uname[33];
uint8_t realm[33];
uint8_t upwd[33];
strcpy((char *)upwd, "VOkJxbRl1RmTxUk/WvJxBt");
res = stun_check_message_integrity_str(TURN_CREDENTIALS_SHORT_TERM, buf, sizeof(reqstc) - 1, uname, realm, upwd, shatype);
printf("RFC 5769 simple request short-term credentials and integrity test result: ");
res = stun_check_message_integrity_str(TURN_CREDENTIALS_SHORT_TERM, buf, sizeof(reqstc) - 1, uname, realm, upwd,
shatype);
printf("RFC 5769 simple request short-term credentials and integrity test result: ");
if (res > 0) {
printf("success\n");
} else if (res == 0) {
printf("failure on integrity check\n");
exit(-1);
} else {
printf("failure on message structure check\n");
exit(-1);
}
}
if (res > 0) {
printf("success\n");
} else if (res == 0) {
printf("failure on integrity check\n");
exit(-1);
} else {
printf("failure on message structure check\n");
exit(-1);
}
}
{//negative fingerprint
buf[27] = 23;
{ // negative fingerprint
buf[27] = 23;
res = stun_is_command_message_full_check_str(buf, sizeof(reqstc) - 1, 1, NULL);
printf("RFC 5769 NEGATIVE fingerprint test(0) result: ");
res = stun_is_command_message_full_check_str(buf, sizeof(reqstc) - 1, 1, NULL);
printf("RFC 5769 NEGATIVE fingerprint test(0) result: ");
if (!res) {
printf("success\n");
} else if (res == 0) {
printf("failure on NEGATIVE fingerprint check\n");
exit(-1);
}
}
}
if (!res) {
printf("success\n");
} else if (res == 0) {
printf("failure on NEGATIVE fingerprint check\n");
exit(-1);
}
}
}
{
const unsigned char reqltc[] = "\x00\x01\x00\x60"
"\x21\x12\xa4\x42"
"\x78\xad\x34\x33\xc6\xad\x72\xc0\x29\xda\x41\x2e"
"\x00\x06\x00\x12"
"\xe3\x83\x9e\xe3\x83\x88\xe3\x83\xaa\xe3\x83\x83"
"\xe3\x82\xaf\xe3\x82\xb9\x00\x00"
"\x00\x15\x00\x1c"
"\x66\x2f\x2f\x34\x39\x39\x6b\x39\x35\x34\x64\x36"
"\x4f\x4c\x33\x34\x6f\x4c\x39\x46\x53\x54\x76\x79"
"\x36\x34\x73\x41"
"\x00\x14\x00\x0b"
"\x65\x78\x61\x6d\x70\x6c\x65\x2e\x6f\x72\x67\x00"
"\x00\x08\x00\x14"
"\xf6\x70\x24\x65\x6d\xd6\x4a\x3e\x02\xb8\xe0\x71"
"\x2e\x85\xc9\xa2\x8c\xa8\x96\x66";
{
const unsigned char reqltc[] = "\x00\x01\x00\x60"
"\x21\x12\xa4\x42"
"\x78\xad\x34\x33\xc6\xad\x72\xc0\x29\xda\x41\x2e"
"\x00\x06\x00\x12"
"\xe3\x83\x9e\xe3\x83\x88\xe3\x83\xaa\xe3\x83\x83"
"\xe3\x82\xaf\xe3\x82\xb9\x00\x00"
"\x00\x15\x00\x1c"
"\x66\x2f\x2f\x34\x39\x39\x6b\x39\x35\x34\x64\x36"
"\x4f\x4c\x33\x34\x6f\x4c\x39\x46\x53\x54\x76\x79"
"\x36\x34\x73\x41"
"\x00\x14\x00\x0b"
"\x65\x78\x61\x6d\x70\x6c\x65\x2e\x6f\x72\x67\x00"
"\x00\x08\x00\x14"
"\xf6\x70\x24\x65\x6d\xd6\x4a\x3e\x02\xb8\xe0\x71"
"\x2e\x85\xc9\xa2\x8c\xa8\x96\x66";
uint8_t user[] = "\xe3\x83\x9e\xe3\x83\x88\xe3\x83\xaa\xe3\x83\x83"
"\xe3\x82\xaf\xe3\x82\xb9";
uint8_t user[] = "\xe3\x83\x9e\xe3\x83\x88\xe3\x83\xaa\xe3\x83\x83"
"\xe3\x82\xaf\xe3\x82\xb9";
uint8_t realm[33];
uint8_t nonce[29];
uint8_t upwd[33];
uint8_t realm[33];
uint8_t nonce[29];
uint8_t upwd[33];
uint8_t buf[sizeof(reqltc)];
memcpy(buf, reqltc, sizeof(reqltc));
uint8_t buf[sizeof(reqltc)];
memcpy(buf, reqltc, sizeof(reqltc));
uint8_t uname[sizeof(user)];
memcpy(uname, user, sizeof(user));
uint8_t uname[sizeof(user)];
memcpy(uname, user, sizeof(user));
strcpy((char*) realm, "example.org");
strcpy((char*) upwd, "TheMatrIX");
strcpy((char*)nonce,"f//499k954d6OL34oL9FSTvy64sA");
strcpy((char *)realm, "example.org");
strcpy((char *)upwd, "TheMatrIX");
strcpy((char *)nonce, "f//499k954d6OL34oL9FSTvy64sA");
res = stun_check_message_integrity_str(TURN_CREDENTIALS_LONG_TERM, buf, sizeof(reqltc) - 1, uname, realm,
upwd, shatype);
res = stun_check_message_integrity_str(TURN_CREDENTIALS_LONG_TERM, buf, sizeof(reqltc) - 1, uname, realm, upwd,
shatype);
printf("RFC 5769 message structure, long-term credentials and integrity test result: ");
printf("RFC 5769 message structure, long-term credentials and integrity test result: ");
if (res > 0) {
printf("success\n");
} else if (res == 0) {
printf("failure on integrity check\n");
exit(-1);
} else {
printf("failure on message structure check\n");
exit(-1);
}
if (res > 0) {
printf("success\n");
} else if (res == 0) {
printf("failure on integrity check\n");
exit(-1);
} else {
printf("failure on message structure check\n");
exit(-1);
}
{ //encoding test
printf("RFC 5769 message encoding test result: ");
size_t len = 0;
uint16_t message_type = STUN_METHOD_BINDING;
stun_tid tid;
uint16_t *buf16 = (uint16_t*)buf;
uint32_t *buf32 = (uint32_t*)buf;
memcpy(tid.tsx_id,"\x78\xad\x34\x33\xc6\xad\x72\xc0\x29\xda\x41\x2e",12);
stun_init_buffer_str(buf,&len);
message_type &= (uint16_t)(0x3FFF);
buf16[0]=nswap16(message_type);
buf16[1]=0;
buf32[1]=nswap32(STUN_MAGIC_COOKIE);
stun_tid_message_cpy(buf, &tid);
stun_attr_add_integrity_by_user_str(buf, &len, uname, realm, upwd, nonce, shatype);
if(len != (sizeof(reqltc)-1)) {
printf("failure: length %d, must be %d\n",(int)len,(int)(sizeof(reqltc)-1));
exit(-1);
}
if(memcmp(buf,reqltc,len)) {
printf("failure: wrong message content\n");
{
int lines = 29;
int line = 0;
int col = 0;
int cols = 4;
for(line = 0;line<lines;line++) {
for(col = 0; col<cols; col++) {
uint8_t c = buf[line*4+col];
printf(" %2x",(int)c);
}
printf("\n");
}
}
exit(-1);
}
printf("success\n");
}
{ // encoding test
printf("RFC 5769 message encoding test result: ");
size_t len = 0;
uint16_t message_type = STUN_METHOD_BINDING;
stun_tid tid;
uint16_t *buf16 = (uint16_t *)buf;
uint32_t *buf32 = (uint32_t *)buf;
memcpy(tid.tsx_id, "\x78\xad\x34\x33\xc6\xad\x72\xc0\x29\xda\x41\x2e", 12);
stun_init_buffer_str(buf, &len);
message_type &= (uint16_t)(0x3FFF);
buf16[0] = nswap16(message_type);
buf16[1] = 0;
buf32[1] = nswap32(STUN_MAGIC_COOKIE);
stun_tid_message_cpy(buf, &tid);
stun_attr_add_integrity_by_user_str(buf, &len, uname, realm, upwd, nonce, shatype);
if (len != (sizeof(reqltc) - 1)) {
printf("failure: length %d, must be %d\n", (int)len, (int)(sizeof(reqltc) - 1));
exit(-1);
}
if (memcmp(buf, reqltc, len)) {
printf("failure: wrong message content\n");
{
int lines = 29;
int line = 0;
int col = 0;
int cols = 4;
for (line = 0; line < lines; line++) {
for (col = 0; col < cols; col++) {
uint8_t c = buf[line * 4 + col];
printf(" %2x", (int)c);
}
printf("\n");
}
}
exit(-1);
}
printf("success\n");
}
//Negative test:
buf[32] = 10;
res = stun_check_message_integrity_str(TURN_CREDENTIALS_LONG_TERM, buf, sizeof(reqltc) - 1, uname, realm,
upwd, shatype);
// Negative test:
buf[32] = 10;
res = stun_check_message_integrity_str(TURN_CREDENTIALS_LONG_TERM, buf, sizeof(reqltc) - 1, uname, realm, upwd,
shatype);
printf("RFC 5769 NEGATIVE long-term credentials test result: ");
printf("RFC 5769 NEGATIVE long-term credentials test result: ");
if (res == 0) {
printf("success\n");
} else {
printf("failure on NEGATIVE long-term credentials check\n");
exit(-1);
}
}
if (res == 0) {
printf("success\n");
} else {
printf("failure on NEGATIVE long-term credentials check\n");
exit(-1);
}
}
{
const unsigned char respv4[] = "\x01\x01\x00\x3c"
"\x21\x12\xa4\x42"
"\xb7\xe7\xa7\x01\xbc\x34\xd6\x86\xfa\x87\xdf\xae"
"\x80\x22\x00\x0b"
"\x74\x65\x73\x74\x20\x76\x65\x63\x74\x6f\x72\x20"
"\x00\x20\x00\x08"
"\x00\x01\xa1\x47\xe1\x12\xa6\x43"
"\x00\x08\x00\x14"
"\x2b\x91\xf5\x99\xfd\x9e\x90\xc3\x8c\x74\x89\xf9"
"\x2a\xf9\xba\x53\xf0\x6b\xe7\xd7"
"\x80\x28\x00\x04"
"\xc0\x7d\x4c\x96";
{
const unsigned char respv4[] = "\x01\x01\x00\x3c"
"\x21\x12\xa4\x42"
"\xb7\xe7\xa7\x01\xbc\x34\xd6\x86\xfa\x87\xdf\xae"
"\x80\x22\x00\x0b"
"\x74\x65\x73\x74\x20\x76\x65\x63\x74\x6f\x72\x20"
"\x00\x20\x00\x08"
"\x00\x01\xa1\x47\xe1\x12\xa6\x43"
"\x00\x08\x00\x14"
"\x2b\x91\xf5\x99\xfd\x9e\x90\xc3\x8c\x74\x89\xf9"
"\x2a\xf9\xba\x53\xf0\x6b\xe7\xd7"
"\x80\x28\x00\x04"
"\xc0\x7d\x4c\x96";
uint8_t buf[sizeof(respv4)];
memcpy(buf, respv4, sizeof(respv4));
uint8_t buf[sizeof(respv4)];
memcpy(buf, respv4, sizeof(respv4));
{//fingerprintfs etc
{ // fingerprintfs etc
res = stun_is_command_message_full_check_str(buf, sizeof(respv4) - 1, 1, NULL);
printf("RFC 5769 message fingerprint test(1) result: ");
res = stun_is_command_message_full_check_str(buf, sizeof(respv4) - 1, 1, NULL);
printf("RFC 5769 message fingerprint test(1) result: ");
if (res) {
printf("success\n");
} else if (res == 0) {
printf("failure on fingerprint(1) check\n");
exit(-1);
}
}
if (res) {
printf("success\n");
} else if (res == 0) {
printf("failure on fingerprint(1) check\n");
exit(-1);
}
}
{//short-term credentials
uint8_t uname[33];
uint8_t realm[33];
uint8_t upwd[33];
strcpy((char*) upwd, "VOkJxbRl1RmTxUk/WvJxBt");
{ // short-term credentials
uint8_t uname[33];
uint8_t realm[33];
uint8_t upwd[33];
strcpy((char *)upwd, "VOkJxbRl1RmTxUk/WvJxBt");
res = stun_check_message_integrity_str(TURN_CREDENTIALS_SHORT_TERM, buf, sizeof(respv4) - 1, uname, realm, upwd, shatype);
printf("RFC 5769 IPv4 response short-term credentials and integrity test result: ");
res = stun_check_message_integrity_str(TURN_CREDENTIALS_SHORT_TERM, buf, sizeof(respv4) - 1, uname, realm, upwd,
shatype);
printf("RFC 5769 IPv4 response short-term credentials and integrity test result: ");
if (res > 0) {
printf("success\n");
} else if (res == 0) {
printf("failure on integrity check\n");
exit(-1);
} else {
printf("failure on message structure check\n");
exit(-1);
}
}
if (res > 0) {
printf("success\n");
} else if (res == 0) {
printf("failure on integrity check\n");
exit(-1);
} else {
printf("failure on message structure check\n");
exit(-1);
}
}
{//negative fingerprint
buf[27] = 23;
{ // negative fingerprint
buf[27] = 23;
res = stun_is_command_message_full_check_str(buf, sizeof(respv4) - 1, 1, NULL);
printf("RFC 5769 NEGATIVE fingerprint test(1) result: ");
res = stun_is_command_message_full_check_str(buf, sizeof(respv4) - 1, 1, NULL);
printf("RFC 5769 NEGATIVE fingerprint test(1) result: ");
if (!res) {
printf("success\n");
} else if (res == 0) {
printf("failure on NEGATIVE fingerprint check\n");
exit(-1);
}
}
if (!res) {
printf("success\n");
} else if (res == 0) {
printf("failure on NEGATIVE fingerprint check\n");
exit(-1);
}
}
{//IPv4 addr
ioa_addr addr4;
ioa_addr addr4_test;
{ // IPv4 addr
ioa_addr addr4;
ioa_addr addr4_test;
printf("RFC 5769 IPv4 encoding result: ");
printf("RFC 5769 IPv4 encoding result: ");
res = stun_attr_get_first_addr_str(buf, sizeof(respv4)-1, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, &addr4, NULL);
if(res < 0) {
printf("failure on message structure check\n");
exit(-1);
}
res = stun_attr_get_first_addr_str(buf, sizeof(respv4) - 1, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, &addr4, NULL);
if (res < 0) {
printf("failure on message structure check\n");
exit(-1);
}
make_ioa_addr((const uint8_t*)"192.0.2.1", 32853, &addr4_test);
if(addr_eq(&addr4,&addr4_test)) {
printf("success\n");
} else {
printf("failure on IPv4 deconding check\n");
exit(-1);
}
}
}
make_ioa_addr((const uint8_t *)"192.0.2.1", 32853, &addr4_test);
if (addr_eq(&addr4, &addr4_test)) {
printf("success\n");
} else {
printf("failure on IPv4 deconding check\n");
exit(-1);
}
}
}
{
const unsigned char respv6[] = "\x01\x01\x00\x48"
"\x21\x12\xa4\x42"
"\xb7\xe7\xa7\x01\xbc\x34\xd6\x86\xfa\x87\xdf\xae"
"\x80\x22\x00\x0b"
"\x74\x65\x73\x74\x20\x76\x65\x63\x74\x6f\x72\x20"
"\x00\x20\x00\x14"
"\x00\x02\xa1\x47"
"\x01\x13\xa9\xfa\xa5\xd3\xf1\x79"
"\xbc\x25\xf4\xb5\xbe\xd2\xb9\xd9"
"\x00\x08\x00\x14"
"\xa3\x82\x95\x4e\x4b\xe6\x7b\xf1\x17\x84\xc9\x7c"
"\x82\x92\xc2\x75\xbf\xe3\xed\x41"
"\x80\x28\x00\x04"
"\xc8\xfb\x0b\x4c";
{
const unsigned char respv6[] = "\x01\x01\x00\x48"
"\x21\x12\xa4\x42"
"\xb7\xe7\xa7\x01\xbc\x34\xd6\x86\xfa\x87\xdf\xae"
"\x80\x22\x00\x0b"
"\x74\x65\x73\x74\x20\x76\x65\x63\x74\x6f\x72\x20"
"\x00\x20\x00\x14"
"\x00\x02\xa1\x47"
"\x01\x13\xa9\xfa\xa5\xd3\xf1\x79"
"\xbc\x25\xf4\xb5\xbe\xd2\xb9\xd9"
"\x00\x08\x00\x14"
"\xa3\x82\x95\x4e\x4b\xe6\x7b\xf1\x17\x84\xc9\x7c"
"\x82\x92\xc2\x75\xbf\xe3\xed\x41"
"\x80\x28\x00\x04"
"\xc8\xfb\x0b\x4c";
uint8_t buf[sizeof(respv6)];
uint8_t buf[sizeof(respv6)];
{ //decoding test
memcpy(buf, respv6, sizeof(respv6));
{ // decoding test
memcpy(buf, respv6, sizeof(respv6));
res = stun_is_command_message_full_check_str(buf, sizeof(respv6) - 1, 1, NULL);
printf("RFC 5769 message fingerprint test(2) result: ");
res = stun_is_command_message_full_check_str(buf, sizeof(respv6) - 1, 1, NULL);
printf("RFC 5769 message fingerprint test(2) result: ");
if (res) {
printf("success\n");
} else if (res == 0) {
printf("failure on fingerprint(2) check\n");
exit(-1);
}
}
if (res) {
printf("success\n");
} else if (res == 0) {
printf("failure on fingerprint(2) check\n");
exit(-1);
}
}
{//short-term credentials test
uint8_t uname[33];
uint8_t realm[33];
uint8_t upwd[33];
strcpy((char*) upwd, "VOkJxbRl1RmTxUk/WvJxBt");
{ // short-term credentials test
uint8_t uname[33];
uint8_t realm[33];
uint8_t upwd[33];
strcpy((char *)upwd, "VOkJxbRl1RmTxUk/WvJxBt");
res = stun_check_message_integrity_str(TURN_CREDENTIALS_SHORT_TERM, buf, sizeof(respv6) - 1, uname, realm, upwd, shatype);
printf("RFC 5769 IPv6 response short-term credentials and integrity test result: ");
res = stun_check_message_integrity_str(TURN_CREDENTIALS_SHORT_TERM, buf, sizeof(respv6) - 1, uname, realm, upwd,
shatype);
printf("RFC 5769 IPv6 response short-term credentials and integrity test result: ");
if (res > 0) {
printf("success\n");
} else if (res == 0) {
printf("failure on integrity check\n");
exit(-1);
} else {
printf("failure on message structure check\n");
exit(-1);
}
}
if (res > 0) {
printf("success\n");
} else if (res == 0) {
printf("failure on integrity check\n");
exit(-1);
} else {
printf("failure on message structure check\n");
exit(-1);
}
}
{//negative decoding test
buf[27] = 23;
{ // negative decoding test
buf[27] = 23;
res = stun_is_command_message_full_check_str(buf, sizeof(respv6) - 1, 1, NULL);
printf("RFC 5769 NEGATIVE fingerprint test(2) result: ");
res = stun_is_command_message_full_check_str(buf, sizeof(respv6) - 1, 1, NULL);
printf("RFC 5769 NEGATIVE fingerprint test(2) result: ");
if (!res) {
printf("success\n");
} else if (res == 0) {
printf("failure on NEGATIVE fingerprint check\n");
exit(-1);
}
}
if (!res) {
printf("success\n");
} else if (res == 0) {
printf("failure on NEGATIVE fingerprint check\n");
exit(-1);
}
}
{//IPv6 deconding test
ioa_addr addr6;
ioa_addr addr6_test;
{ // IPv6 deconding test
ioa_addr addr6;
ioa_addr addr6_test;
printf("RFC 5769 IPv6 encoding result: ");
printf("RFC 5769 IPv6 encoding result: ");
res = stun_attr_get_first_addr_str(buf, sizeof(respv6) - 1,
STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, &addr6, NULL);
if (res < 0) {
printf("failure on message structure check\n");
exit(-1);
}
res = stun_attr_get_first_addr_str(buf, sizeof(respv6) - 1, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, &addr6, NULL);
if (res < 0) {
printf("failure on message structure check\n");
exit(-1);
}
make_ioa_addr((const uint8_t*) "2001:db8:1234:5678:11:2233:4455:6677", 32853, &addr6_test);
if (addr_eq(&addr6, &addr6_test)) {
printf("success\n");
} else {
printf("failure on IPv6 deconding check\n");
exit(-1);
}
}
}
make_ioa_addr((const uint8_t *)"2001:db8:1234:5678:11:2233:4455:6677", 32853, &addr6_test);
if (addr_eq(&addr6, &addr6_test)) {
printf("success\n");
} else {
printf("failure on IPv6 deconding check\n");
exit(-1);
}
}
}
{
if(check_oauth()<0)
exit(-1);
}
{
if (check_oauth() < 0)
exit(-1);
}
return 0;
return 0;
}

View File

@ -28,21 +28,21 @@
* SUCH DAMAGE.
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#if defined(_MSC_VER)
#include <getopt.h>
#include <getopt.h>
#else
#include <unistd.h>
#if !defined(WINDOWS)
#include <err.h>
#endif
#include <unistd.h>
#if !defined(WINDOWS)
#include <err.h>
#endif
#endif
#include "ns_turn_utils.h"
#include "apputils.h"
#include "ns_turn_utils.h"
#include "stun_buffer.h"
#ifdef __cplusplus
@ -57,383 +57,380 @@ static int counter = 0;
#ifdef __cplusplus
static int run_stunclient(const char* rip, int rport, int *port, int *rfc5780, int response_port, int change_ip, int change_port, int padding)
{
static int run_stunclient(const char *rip, int rport, int *port, int *rfc5780, int response_port, int change_ip,
int change_port, int padding) {
ioa_addr remote_addr;
int new_udp_fd = -1;
ioa_addr remote_addr;
int new_udp_fd = -1;
memset((void *) &remote_addr, 0, sizeof(ioa_addr));
if (make_ioa_addr((const uint8_t*) rip, rport, &remote_addr) < 0)
err(-1, NULL);
memset((void *)&remote_addr, 0, sizeof(ioa_addr));
if (make_ioa_addr((const uint8_t *)rip, rport, &remote_addr) < 0)
err(-1, NULL);
if (udp_fd < 0) {
udp_fd = socket(remote_addr.ss.sa_family, SOCK_DGRAM, 0);
if (udp_fd < 0)
err(-1, NULL);
if (udp_fd < 0) {
udp_fd = socket(remote_addr.ss.sa_family, SOCK_DGRAM, 0);
if (udp_fd < 0)
err(-1, NULL);
if (!addr_any(&real_local_addr)) {
if (addr_bind(udp_fd, &real_local_addr,0,1,UDP_SOCKET) < 0)
err(-1, NULL);
}
}
if (!addr_any(&real_local_addr)) {
if (addr_bind(udp_fd, &real_local_addr, 0, 1, UDP_SOCKET) < 0)
err(-1, NULL);
}
}
if (response_port >= 0) {
if (response_port >= 0) {
new_udp_fd = socket(remote_addr.ss.sa_family, SOCK_DGRAM, 0);
if (new_udp_fd < 0)
err(-1, NULL);
new_udp_fd = socket(remote_addr.ss.sa_family, SOCK_DGRAM, 0);
if (new_udp_fd < 0)
err(-1, NULL);
addr_set_port(&real_local_addr, response_port);
addr_set_port(&real_local_addr, response_port);
if (addr_bind(new_udp_fd, &real_local_addr, 0, 1, UDP_SOCKET) < 0)
err(-1, NULL);
}
if (addr_bind(new_udp_fd, &real_local_addr, 0, 1, UDP_SOCKET) < 0)
err(-1, NULL);
}
turn::StunMsgRequest req(STUN_METHOD_BINDING);
turn::StunMsgRequest req(STUN_METHOD_BINDING);
req.constructBindingRequest();
req.constructBindingRequest();
if (response_port >= 0) {
turn::StunAttrResponsePort rpa;
rpa.setResponsePort((uint16_t)response_port);
try {
req.addAttr(rpa);
} catch(turn::WrongStunAttrFormatException &ex1) {
printf("Wrong rp attr format\n");
exit(-1);
} catch(turn::WrongStunBufferFormatException &ex2) {
printf("Wrong stun buffer format (1)\n");
exit(-1);
} catch(...) {
printf("Wrong something (1)\n");
exit(-1);
}
}
if (change_ip || change_port) {
turn::StunAttrChangeRequest cra;
cra.setChangeIp(change_ip);
cra.setChangePort(change_port);
try {
req.addAttr(cra);
} catch(turn::WrongStunAttrFormatException &ex1) {
printf("Wrong cr attr format\n");
exit(-1);
} catch(turn::WrongStunBufferFormatException &ex2) {
printf("Wrong stun buffer format (2)\n");
exit(-1);
} catch(...) {
printf("Wrong something (2)\n");
exit(-1);
}
}
if (padding) {
turn::StunAttrPadding pa;
pa.setPadding(1500);
try {
req.addAttr(pa);
} catch(turn::WrongStunAttrFormatException &ex1) {
printf("Wrong p attr format\n");
exit(-1);
} catch(turn::WrongStunBufferFormatException &ex2) {
printf("Wrong stun buffer format (3)\n");
exit(-1);
} catch(...) {
printf("Wrong something (3)\n");
exit(-1);
}
}
if (response_port >= 0) {
turn::StunAttrResponsePort rpa;
rpa.setResponsePort((uint16_t)response_port);
try {
req.addAttr(rpa);
} catch (turn::WrongStunAttrFormatException &ex1) {
printf("Wrong rp attr format\n");
exit(-1);
} catch (turn::WrongStunBufferFormatException &ex2) {
printf("Wrong stun buffer format (1)\n");
exit(-1);
} catch (...) {
printf("Wrong something (1)\n");
exit(-1);
}
}
if (change_ip || change_port) {
turn::StunAttrChangeRequest cra;
cra.setChangeIp(change_ip);
cra.setChangePort(change_port);
try {
req.addAttr(cra);
} catch (turn::WrongStunAttrFormatException &ex1) {
printf("Wrong cr attr format\n");
exit(-1);
} catch (turn::WrongStunBufferFormatException &ex2) {
printf("Wrong stun buffer format (2)\n");
exit(-1);
} catch (...) {
printf("Wrong something (2)\n");
exit(-1);
}
}
if (padding) {
turn::StunAttrPadding pa;
pa.setPadding(1500);
try {
req.addAttr(pa);
} catch (turn::WrongStunAttrFormatException &ex1) {
printf("Wrong p attr format\n");
exit(-1);
} catch (turn::WrongStunBufferFormatException &ex2) {
printf("Wrong stun buffer format (3)\n");
exit(-1);
} catch (...) {
printf("Wrong something (3)\n");
exit(-1);
}
}
{
int len = 0;
int slen = get_ioa_addr_len(&remote_addr);
{
int len = 0;
int slen = get_ioa_addr_len(&remote_addr);
do {
len = sendto(udp_fd, req.getRawBuffer(), req.getSize(), 0, (struct sockaddr*) &remote_addr, (socklen_t) slen);
} while (len < 0 && ((errno == EINTR) || (errno == ENOBUFS) || (errno == EAGAIN)));
do {
len = sendto(udp_fd, req.getRawBuffer(), req.getSize(), 0, (struct sockaddr *)&remote_addr, (socklen_t)slen);
} while (len < 0 && ((errno == EINTR) || (errno == ENOBUFS) || (errno == EAGAIN)));
if (len < 0)
err(-1, NULL);
if (len < 0)
err(-1, NULL);
}
}
if (addr_get_from_sock(udp_fd, &real_local_addr) < 0) {
printf("%s: Cannot get address from local socket\n", __FUNCTION__);
} else {
*port = addr_get_port(&real_local_addr);
}
if (addr_get_from_sock(udp_fd, &real_local_addr) < 0) {
printf("%s: Cannot get address from local socket\n", __FUNCTION__);
} else {
*port = addr_get_port(&real_local_addr);
}
{
if (new_udp_fd >= 0) {
close(udp_fd);
udp_fd = new_udp_fd;
new_udp_fd = -1;
}
}
{
if(new_udp_fd >= 0) {
close(udp_fd);
udp_fd = new_udp_fd;
new_udp_fd = -1;
}
}
{
int len = 0;
stun_buffer buf;
uint8_t *ptr = buf.buf;
int recvd = 0;
const int to_recv = sizeof(buf.buf);
{
int len = 0;
stun_buffer buf;
uint8_t *ptr = buf.buf;
int recvd = 0;
const int to_recv = sizeof(buf.buf);
do {
len = recv(udp_fd, ptr, to_recv - recvd, 0);
if (len > 0) {
recvd += len;
ptr += len;
break;
}
} while (len < 0 && (errno == EINTR));
do {
len = recv(udp_fd, ptr, to_recv - recvd, 0);
if (len > 0) {
recvd += len;
ptr += len;
break;
}
} while (len < 0 && (errno == EINTR));
if (recvd > 0)
len = recvd;
buf.len = len;
if (recvd > 0)
len = recvd;
buf.len = len;
try {
turn::StunMsgResponse res(buf.buf, sizeof(buf.buf), (size_t)buf.len, true);
try {
turn::StunMsgResponse res(buf.buf, sizeof(buf.buf), (size_t)buf.len, true);
if (res.isCommand()) {
if (res.isCommand()) {
if (res.isSuccess()) {
if(res.isSuccess()) {
if (res.isBindingResponse()) {
if (res.isBindingResponse()) {
ioa_addr reflexive_addr;
addr_set_any(&reflexive_addr);
turn::StunAttrIterator iter(res, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS);
if (!iter.eof()) {
ioa_addr reflexive_addr;
addr_set_any(&reflexive_addr);
turn::StunAttrIterator iter(res,STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS);
if (!iter.eof()) {
turn::StunAttrAddr addr(iter);
addr.getAddr(reflexive_addr);
turn::StunAttrAddr addr(iter);
addr.getAddr(reflexive_addr);
turn::StunAttrIterator iter1(res, STUN_ATTRIBUTE_OTHER_ADDRESS);
if (!iter1.eof()) {
*rfc5780 = 1;
printf("\n========================================\n");
printf("RFC 5780 response %d\n", ++counter);
ioa_addr other_addr;
turn::StunAttrAddr addr1(iter1);
addr1.getAddr(other_addr);
turn::StunAttrIterator iter2(res, STUN_ATTRIBUTE_RESPONSE_ORIGIN);
if (!iter2.eof()) {
ioa_addr response_origin;
turn::StunAttrAddr addr2(iter2);
addr2.getAddr(response_origin);
addr_debug_print(1, &response_origin, "Response origin: ");
}
addr_debug_print(1, &other_addr, "Other addr: ");
}
addr_debug_print(1, &reflexive_addr, "UDP reflexive addr");
turn::StunAttrIterator iter1(res,STUN_ATTRIBUTE_OTHER_ADDRESS);
if (!iter1.eof()) {
*rfc5780 = 1;
printf("\n========================================\n");
printf("RFC 5780 response %d\n",++counter);
ioa_addr other_addr;
turn::StunAttrAddr addr1(iter1);
addr1.getAddr(other_addr);
turn::StunAttrIterator iter2(res,STUN_ATTRIBUTE_RESPONSE_ORIGIN);
if (!iter2.eof()) {
ioa_addr response_origin;
turn::StunAttrAddr addr2(iter2);
addr2.getAddr(response_origin);
addr_debug_print(1, &response_origin, "Response origin: ");
}
addr_debug_print(1, &other_addr, "Other addr: ");
}
addr_debug_print(1, &reflexive_addr, "UDP reflexive addr");
} else {
printf("Cannot read the response\n");
}
} else {
printf("Wrong type of response\n");
}
} else {
int err_code = res.getError();
std::string reason = res.getReason();
} else {
printf("Cannot read the response\n");
}
} else {
printf("Wrong type of response\n");
}
} else {
int err_code = res.getError();
std::string reason = res.getReason();
printf("The response is an error %d (%s)\n", err_code, reason.c_str());
}
} else {
printf("The response is not a response message\n");
}
} catch (...) {
printf("The response is not a well formed STUN message\n");
}
}
printf("The response is an error %d (%s)\n", err_code, reason.c_str());
}
} else {
printf("The response is not a response message\n");
}
} catch(...) {
printf("The response is not a well formed STUN message\n");
}
}
return 0;
return 0;
}
#else
static int run_stunclient(const char* rip, int rport, int *port, int *rfc5780, int response_port, int change_ip, int change_port, int padding)
{
static int run_stunclient(const char *rip, int rport, int *port, int *rfc5780, int response_port, int change_ip,
int change_port, int padding) {
ioa_addr remote_addr;
int new_udp_fd = -1;
stun_buffer buf;
ioa_addr remote_addr;
int new_udp_fd = -1;
stun_buffer buf;
memset(&remote_addr, 0, sizeof(remote_addr));
if (make_ioa_addr((const uint8_t*) rip, rport, &remote_addr) < 0)
err(-1, NULL);
memset(&remote_addr, 0, sizeof(remote_addr));
if (make_ioa_addr((const uint8_t *)rip, rport, &remote_addr) < 0)
err(-1, NULL);
if (udp_fd < 0) {
udp_fd = socket(remote_addr.ss.sa_family, CLIENT_DGRAM_SOCKET_TYPE, CLIENT_DGRAM_SOCKET_PROTOCOL);
if (udp_fd < 0)
err(-1, NULL);
if (udp_fd < 0) {
udp_fd = socket(remote_addr.ss.sa_family, CLIENT_DGRAM_SOCKET_TYPE, CLIENT_DGRAM_SOCKET_PROTOCOL);
if (udp_fd < 0)
err(-1, NULL);
if (!addr_any(&real_local_addr)) {
if (addr_bind(udp_fd, &real_local_addr,0,1,UDP_SOCKET) < 0)
err(-1, NULL);
}
}
if (!addr_any(&real_local_addr)) {
if (addr_bind(udp_fd, &real_local_addr, 0, 1, UDP_SOCKET) < 0)
err(-1, NULL);
}
}
if (response_port >= 0) {
if (response_port >= 0) {
new_udp_fd = socket(remote_addr.ss.sa_family, CLIENT_DGRAM_SOCKET_TYPE, CLIENT_DGRAM_SOCKET_PROTOCOL);
if (new_udp_fd < 0)
err(-1, NULL);
new_udp_fd = socket(remote_addr.ss.sa_family, CLIENT_DGRAM_SOCKET_TYPE, CLIENT_DGRAM_SOCKET_PROTOCOL);
if (new_udp_fd < 0)
err(-1, NULL);
addr_set_port(&real_local_addr, response_port);
addr_set_port(&real_local_addr, response_port);
if (addr_bind(new_udp_fd, &real_local_addr,0,1,UDP_SOCKET) < 0)
err(-1, NULL);
}
if (addr_bind(new_udp_fd, &real_local_addr, 0, 1, UDP_SOCKET) < 0)
err(-1, NULL);
}
stun_prepare_binding_request(&buf);
stun_prepare_binding_request(&buf);
if (response_port >= 0) {
stun_attr_add_response_port_str((uint8_t*) (buf.buf), (size_t*) &(buf.len), (uint16_t) response_port);
}
if (change_ip || change_port) {
stun_attr_add_change_request_str((uint8_t*) buf.buf, (size_t*) &(buf.len), change_ip, change_port);
}
if (padding) {
if(stun_attr_add_padding_str((uint8_t*) buf.buf, (size_t*) &(buf.len), 1500)<0) {
printf("%s: ERROR: Cannot add padding\n",__FUNCTION__);
}
}
if (response_port >= 0) {
stun_attr_add_response_port_str((uint8_t *)(buf.buf), (size_t *)&(buf.len), (uint16_t)response_port);
}
if (change_ip || change_port) {
stun_attr_add_change_request_str((uint8_t *)buf.buf, (size_t *)&(buf.len), change_ip, change_port);
}
if (padding) {
if (stun_attr_add_padding_str((uint8_t *)buf.buf, (size_t *)&(buf.len), 1500) < 0) {
printf("%s: ERROR: Cannot add padding\n", __FUNCTION__);
}
}
{
int len = 0;
int slen = get_ioa_addr_len(&remote_addr);
{
int len = 0;
int slen = get_ioa_addr_len(&remote_addr);
do {
len = sendto(udp_fd, buf.buf, buf.len, 0, (struct sockaddr*) &remote_addr, (socklen_t) slen);
} while (len < 0 && ((errno == EINTR) || (errno == ENOBUFS) || (errno == EAGAIN)));
do {
len = sendto(udp_fd, buf.buf, buf.len, 0, (struct sockaddr *)&remote_addr, (socklen_t)slen);
} while (len < 0 && ((errno == EINTR) || (errno == ENOBUFS) || (errno == EAGAIN)));
if (len < 0)
err(-1, NULL);
if (len < 0)
err(-1, NULL);
}
}
if (addr_get_from_sock(udp_fd, &real_local_addr) < 0) {
printf("%s: Cannot get address from local socket\n", __FUNCTION__);
} else {
*port = addr_get_port(&real_local_addr);
}
if (addr_get_from_sock(udp_fd, &real_local_addr) < 0) {
printf("%s: Cannot get address from local socket\n", __FUNCTION__);
} else {
*port = addr_get_port(&real_local_addr);
}
{
if (new_udp_fd >= 0) {
socket_closesocket(udp_fd);
udp_fd = new_udp_fd;
new_udp_fd = -1;
}
}
{
if(new_udp_fd >= 0) {
socket_closesocket(udp_fd);
udp_fd = new_udp_fd;
new_udp_fd = -1;
}
}
{
int len = 0;
uint8_t *ptr = buf.buf;
int recvd = 0;
const int to_recv = sizeof(buf.buf);
{
int len = 0;
uint8_t *ptr = buf.buf;
int recvd = 0;
const int to_recv = sizeof(buf.buf);
do {
len = recv(udp_fd, ptr, to_recv - recvd, 0);
if (len > 0) {
recvd += len;
ptr += len;
break;
}
} while (len < 0 && ((errno == EINTR) || (errno == EAGAIN)));
do {
len = recv(udp_fd, ptr, to_recv - recvd, 0);
if (len > 0) {
recvd += len;
ptr += len;
break;
}
} while (len < 0 && ((errno == EINTR) || (errno == EAGAIN)));
if (recvd > 0)
len = recvd;
buf.len = len;
if (recvd > 0)
len = recvd;
buf.len = len;
if (stun_is_command_message(&buf)) {
if (stun_is_command_message(&buf)) {
if (stun_is_response(&buf)) {
if (stun_is_response(&buf)) {
if (stun_is_success_response(&buf)) {
if (stun_is_success_response(&buf)) {
if (stun_is_binding_response(&buf)) {
if (stun_is_binding_response(&buf)) {
ioa_addr reflexive_addr;
addr_set_any(&reflexive_addr);
if (stun_attr_get_first_addr(&buf, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, &reflexive_addr, NULL) >= 0) {
ioa_addr reflexive_addr;
addr_set_any(&reflexive_addr);
if (stun_attr_get_first_addr(&buf, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, &reflexive_addr, NULL) >= 0) {
stun_attr_ref sar = stun_attr_get_first_by_type_str(buf.buf, buf.len, STUN_ATTRIBUTE_OTHER_ADDRESS);
if (sar) {
*rfc5780 = 1;
printf("\n========================================\n");
printf("RFC 5780 response %d\n", ++counter);
ioa_addr other_addr;
stun_attr_get_addr_str((uint8_t *)buf.buf, (size_t)buf.len, sar, &other_addr, NULL);
sar = stun_attr_get_first_by_type_str(buf.buf, buf.len, STUN_ATTRIBUTE_RESPONSE_ORIGIN);
if (sar) {
ioa_addr response_origin;
stun_attr_get_addr_str((uint8_t *)buf.buf, (size_t)buf.len, sar, &response_origin, NULL);
addr_debug_print(1, &response_origin, "Response origin: ");
}
addr_debug_print(1, &other_addr, "Other addr: ");
}
addr_debug_print(1, &reflexive_addr, "UDP reflexive addr");
stun_attr_ref sar = stun_attr_get_first_by_type_str(buf.buf, buf.len, STUN_ATTRIBUTE_OTHER_ADDRESS);
if (sar) {
*rfc5780 = 1;
printf("\n========================================\n");
printf("RFC 5780 response %d\n",++counter);
ioa_addr other_addr;
stun_attr_get_addr_str((uint8_t *) buf.buf, (size_t) buf.len, sar, &other_addr, NULL);
sar = stun_attr_get_first_by_type_str(buf.buf, buf.len, STUN_ATTRIBUTE_RESPONSE_ORIGIN);
if (sar) {
ioa_addr response_origin;
stun_attr_get_addr_str((uint8_t *) buf.buf, (size_t) buf.len, sar, &response_origin, NULL);
addr_debug_print(1, &response_origin, "Response origin: ");
}
addr_debug_print(1, &other_addr, "Other addr: ");
}
addr_debug_print(1, &reflexive_addr, "UDP reflexive addr");
} else {
printf("Cannot read the response\n");
}
} else {
printf("Wrong type of response\n");
}
} else {
int err_code = 0;
uint8_t err_msg[1025] = "\0";
size_t err_msg_size = sizeof(err_msg);
if (stun_is_error_response(&buf, &err_code, err_msg, err_msg_size)) {
printf("The response is an error %d (%s)\n", err_code, (char *)err_msg);
} else {
printf("The response is an unrecognized error\n");
}
}
} else {
printf("The response is not a response message\n");
}
} else {
printf("The response is not a STUN message\n");
}
}
} else {
printf("Cannot read the response\n");
}
} else {
printf("Wrong type of response\n");
}
} else {
int err_code = 0;
uint8_t err_msg[1025] = "\0";
size_t err_msg_size = sizeof(err_msg);
if (stun_is_error_response(&buf, &err_code, err_msg, err_msg_size)) {
printf("The response is an error %d (%s)\n", err_code, (char*) err_msg);
} else {
printf("The response is an unrecognized error\n");
}
}
} else {
printf("The response is not a response message\n");
}
} else {
printf("The response is not a STUN message\n");
}
}
return 0;
return 0;
}
#endif
//////////////// local definitions /////////////////
static char Usage[] =
"Usage: stunclient [options] address\n"
"Options:\n"
" -p STUN server port (Default: 3478)\n"
" -L Local address to use (optional)\n"
" -f Force RFC 5780 processing\n";
static char Usage[] = "Usage: stunclient [options] address\n"
"Options:\n"
" -p STUN server port (Default: 3478)\n"
" -L Local address to use (optional)\n"
" -f Force RFC 5780 processing\n";
//////////////////////////////////////////////////
int main(int argc, char **argv)
{
int main(int argc, char **argv) {
int port = DEFAULT_STUN_PORT;
char local_addr[256]="\0";
int c=0;
char local_addr[256] = "\0";
int c = 0;
int forceRfc5780 = 0;
if (socket_init()) return -1;
if (socket_init())
return -1;
set_logfile("stdout");
set_no_stdout_log(1);
set_system_parameters(0);
memset(local_addr, 0, sizeof(local_addr));
while ((c = getopt(argc, argv, "p:L:f")) != -1) {
switch(c) {
switch (c) {
case 'f':
forceRfc5780 = 1;
break;
forceRfc5780 = 1;
break;
case 'p':
port = atoi(optarg);
break;
@ -441,32 +438,32 @@ int main(int argc, char **argv)
STRCPY(local_addr, optarg);
break;
default:
fprintf(stderr,"%s\n", Usage);
fprintf(stderr, "%s\n", Usage);
exit(1);
}
}
if(optind>=argc) {
if (optind >= argc) {
fprintf(stderr, "%s\n", Usage);
exit(-1);
}
addr_set_any(&real_local_addr);
if(local_addr[0]) {
if(make_ioa_addr((const uint8_t*)local_addr, 0, &real_local_addr)<0) {
err(-1,NULL);
}
if (local_addr[0]) {
if (make_ioa_addr((const uint8_t *)local_addr, 0, &real_local_addr) < 0) {
err(-1, NULL);
}
}
int local_port = -1;
int rfc5780 = 0;
run_stunclient(argv[optind], port, &local_port, &rfc5780,-1,0,0,0);
run_stunclient(argv[optind], port, &local_port, &rfc5780, -1, 0, 0, 0);
if(rfc5780 || forceRfc5780) {
run_stunclient(argv[optind], port, &local_port, &rfc5780,local_port+1,1,1,0);
run_stunclient(argv[optind], port, &local_port, &rfc5780,-1,1,1,1);
if (rfc5780 || forceRfc5780) {
run_stunclient(argv[optind], port, &local_port, &rfc5780, local_port + 1, 1, 1, 0);
run_stunclient(argv[optind], port, &local_port, &rfc5780, -1, 1, 1, 1);
}
socket_closesocket(udp_fd);

View File

@ -29,13 +29,13 @@
*/
#include "apputils.h"
#include "uclient.h"
#include "ns_turn_utils.h"
#include "session.h"
#include "stun_buffer.h"
#include "uclient.h"
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
@ -47,28 +47,28 @@
/////////////// extern definitions /////////////////////
int clmessage_length=100;
int do_not_use_channel=0;
int c2c=0;
int clnet_verbose=TURN_VERBOSE_NONE;
int use_tcp=0;
int use_sctp=0;
int use_secure=0;
int hang_on=0;
int clmessage_length = 100;
int do_not_use_channel = 0;
int c2c = 0;
int clnet_verbose = TURN_VERBOSE_NONE;
int use_tcp = 0;
int use_sctp = 0;
int use_secure = 0;
int hang_on = 0;
ioa_addr peer_addr;
int no_rtcp = 0;
int default_address_family = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_DEFAULT;
int dont_fragment = 0;
uint8_t g_uname[STUN_MAX_USERNAME_SIZE+1];
uint8_t g_uname[STUN_MAX_USERNAME_SIZE + 1];
password_t g_upwd;
char g_auth_secret[1025]="\0";
char g_auth_secret[1025] = "\0";
int g_use_auth_secret_with_timestamp = 0;
int use_fingerprints = 1;
static char ca_cert_file[1025]="";
static char cipher_suite[1025]="";
char cert_file[1025]="";
char pkey_file[1025]="";
static char ca_cert_file[1025] = "";
static char cipher_suite[1025] = "";
char cert_file[1025] = "";
char pkey_file[1025] = "";
SSL_CTX *root_tls_ctx[32];
int root_tls_ctx_num = 0;
@ -89,7 +89,7 @@ int no_permissions = 0;
int extra_requests = 0;
char origin[STUN_MAX_ORIGIN_SIZE+1] = "\0";
char origin[STUN_MAX_ORIGIN_SIZE + 1] = "\0";
band_limit_t bps = 0;
@ -99,502 +99,485 @@ int oauth = 0;
oauth_key okey_array[3];
static oauth_key_data_raw okdr_array[3] = {
{"north","MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEK",0,0,"A256GCM","crinna.org"},
{"union","MTIzNDU2Nzg5MDEyMzQ1Ngo=",0,0,"A128GCM","north.gov"},
{"oldempire","MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIK",0,0,"A256GCM",""}
};
{"north", "MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEK", 0, 0, "A256GCM", "crinna.org"},
{"union", "MTIzNDU2Nzg5MDEyMzQ1Ngo=", 0, 0, "A128GCM", "north.gov"},
{"oldempire", "MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIK", 0, 0, "A256GCM", ""}};
//////////////// local definitions /////////////////
static char Usage[] =
"Usage: uclient [flags] [options] turn-server-ip-address\n"
"Flags:\n"
" -t TCP (default - UDP).\n"
" -b SCTP (default - UDP).\n"
" -T TCP relay transport (default - UDP). Implies options -t, -y, -c, and ignores \n"
" options -s, -e, -r and -g. Can be used together with -b\n"
" -P Passive TCP (RFC6062 with active peer). Implies -T.\n"
" -S Secure connection: TLS for TCP, DTLS for UDP.\n"
" -U Secure connection with eNULL cipher.\n"
" -v Verbose.\n"
" -s Use send method.\n"
" -y Use client-to-client connections.\n"
" -h Hang on indefinitely after the last sent packet.\n"
" -c No rtcp connections.\n"
" -x IPv6 relay address requested.\n"
" -X IPv4 relay address explicitly requested.\n"
" -g Include DONT_FRAGMENT option.\n"
" -D Mandatory channel padding (like in pjnath).\n"
" -N Negative tests (some limited cases only).\n"
" -R Negative protocol tests.\n"
" -O DOS attack mode (quick connect and exit).\n"
" -M ICE Mobility engaged.\n"
" -I Do not set permissions on TURN relay endpoints\n"
" (for testing the non-standard server relay functionality).\n"
" -G Generate extra requests (create permissions, channel bind).\n"
" -B Random disconnect after a few initial packets.\n"
" -Z Dual allocation (implies -c).\n"
" -J Use oAuth with default test keys kid='north', 'union' or 'oldempire'.\n"
"Options:\n"
" -l Message length (Default: 100 Bytes).\n"
" -i Certificate file (for secure connections only, optional).\n"
" -k Private key file (for secure connections only).\n"
" -E CA file for server certificate verification, \n"
" if the server certificate to be verified.\n"
" -p TURN server port (Default: 3478 unsecure, 5349 secure).\n"
" -n Number of messages to send (Default: 5).\n"
" -d Local interface device (optional).\n"
" -L Local address.\n"
" -m Number of clients (default is 1).\n"
" -e Peer address.\n"
" -r Peer port (default 3480).\n"
" -z Per-session packet interval in milliseconds (default is 20 ms).\n"
" -u STUN/TURN user name.\n"
" -w STUN/TURN user password.\n"
" -W TURN REST API \"plain text\" secret.\n"
" -C TURN REST API timestamp/username separator symbol (character). The default value is ':'.\n"
" -F <cipher-suite> Cipher suite for TLS/DTLS. Default value is DEFAULT.\n"
" -o <origin> - the ORIGIN STUN attribute value.\n"
" -a <bytes-per-second> Bandwidth for the bandwidth request in ALLOCATE. The default value is zero.\n";
"Usage: uclient [flags] [options] turn-server-ip-address\n"
"Flags:\n"
" -t TCP (default - UDP).\n"
" -b SCTP (default - UDP).\n"
" -T TCP relay transport (default - UDP). Implies options -t, -y, -c, and ignores \n"
" options -s, -e, -r and -g. Can be used together with -b\n"
" -P Passive TCP (RFC6062 with active peer). Implies -T.\n"
" -S Secure connection: TLS for TCP, DTLS for UDP.\n"
" -U Secure connection with eNULL cipher.\n"
" -v Verbose.\n"
" -s Use send method.\n"
" -y Use client-to-client connections.\n"
" -h Hang on indefinitely after the last sent packet.\n"
" -c No rtcp connections.\n"
" -x IPv6 relay address requested.\n"
" -X IPv4 relay address explicitly requested.\n"
" -g Include DONT_FRAGMENT option.\n"
" -D Mandatory channel padding (like in pjnath).\n"
" -N Negative tests (some limited cases only).\n"
" -R Negative protocol tests.\n"
" -O DOS attack mode (quick connect and exit).\n"
" -M ICE Mobility engaged.\n"
" -I Do not set permissions on TURN relay endpoints\n"
" (for testing the non-standard server relay functionality).\n"
" -G Generate extra requests (create permissions, channel bind).\n"
" -B Random disconnect after a few initial packets.\n"
" -Z Dual allocation (implies -c).\n"
" -J Use oAuth with default test keys kid='north', 'union' or 'oldempire'.\n"
"Options:\n"
" -l Message length (Default: 100 Bytes).\n"
" -i Certificate file (for secure connections only, optional).\n"
" -k Private key file (for secure connections only).\n"
" -E CA file for server certificate verification, \n"
" if the server certificate to be verified.\n"
" -p TURN server port (Default: 3478 unsecure, 5349 secure).\n"
" -n Number of messages to send (Default: 5).\n"
" -d Local interface device (optional).\n"
" -L Local address.\n"
" -m Number of clients (default is 1).\n"
" -e Peer address.\n"
" -r Peer port (default 3480).\n"
" -z Per-session packet interval in milliseconds (default is 20 ms).\n"
" -u STUN/TURN user name.\n"
" -w STUN/TURN user password.\n"
" -W TURN REST API \"plain text\" secret.\n"
" -C TURN REST API timestamp/username separator symbol (character). The default value is ':'.\n"
" -F <cipher-suite> Cipher suite for TLS/DTLS. Default value is DEFAULT.\n"
" -o <origin> - the ORIGIN STUN attribute value.\n"
" -a <bytes-per-second> Bandwidth for the bandwidth request in ALLOCATE. The default value is zero.\n";
//////////////////////////////////////////////////
int main(int argc, char **argv)
{
int port = 0;
int messagenumber = 5;
char local_addr[256];
int c;
int mclient = 1;
char peer_address[129] = "\0";
int peer_port = PEER_DEFAULT_PORT;
int main(int argc, char **argv) {
int port = 0;
int messagenumber = 5;
char local_addr[256];
int c;
int mclient = 1;
char peer_address[129] = "\0";
int peer_port = PEER_DEFAULT_PORT;
char rest_api_separator = ':';
int use_null_cipher=0;
char rest_api_separator = ':';
int use_null_cipher = 0;
#if defined(WINDOWS)
WORD wVersionRequested;
WSADATA wsaData;
int err;
WORD wVersionRequested;
WSADATA wsaData;
int err;
/* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */
wVersionRequested = MAKEWORD(2, 2);
/* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */
wVersionRequested = MAKEWORD(2, 2);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0) {
/* Tell the user that we could not find a usable */
/* Winsock DLL. */
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "WSAStartup failed with error: %d\n", err);
return 1;
}
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0) {
/* Tell the user that we could not find a usable */
/* Winsock DLL. */
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "WSAStartup failed with error: %d\n", err);
return 1;
}
#endif
set_logfile("stdout");
set_no_stdout_log(1);
set_logfile("stdout");
set_no_stdout_log(1);
set_execdir();
set_execdir();
set_system_parameters(0);
set_system_parameters(0);
memset(local_addr, 0, sizeof(local_addr));
memset(local_addr, 0, sizeof(local_addr));
while ((c = getopt(argc, argv, "a:d:p:l:n:L:m:e:r:u:w:i:k:z:W:C:E:F:o:bZvsyhcxXgtTSAPDNOUMRIGBJ")) != -1) {
switch (c){
case 'J': {
while ((c = getopt(argc, argv, "a:d:p:l:n:L:m:e:r:u:w:i:k:z:W:C:E:F:o:bZvsyhcxXgtTSAPDNOUMRIGBJ")) != -1) {
switch (c) {
case 'J': {
oauth = 1;
oauth = 1;
oauth_key_data okd_array[3];
convert_oauth_key_data_raw(&okdr_array[0], &okd_array[0]);
convert_oauth_key_data_raw(&okdr_array[1], &okd_array[1]);
convert_oauth_key_data_raw(&okdr_array[2], &okd_array[2]);
oauth_key_data okd_array[3];
convert_oauth_key_data_raw(&okdr_array[0], &okd_array[0]);
convert_oauth_key_data_raw(&okdr_array[1], &okd_array[1]);
convert_oauth_key_data_raw(&okdr_array[2], &okd_array[2]);
char err_msg[1025] = "\0";
size_t err_msg_size = sizeof(err_msg) - 1;
char err_msg[1025] = "\0";
size_t err_msg_size = sizeof(err_msg) - 1;
if (convert_oauth_key_data(&okd_array[0], &okey_array[0], err_msg, err_msg_size) < 0) {
fprintf(stderr, "%s\n", err_msg);
exit(-1);
}
if (convert_oauth_key_data(&okd_array[0], &okey_array[0], err_msg, err_msg_size) < 0) {
fprintf(stderr, "%s\n", err_msg);
exit(-1);
}
if (convert_oauth_key_data(&okd_array[1], &okey_array[1], err_msg, err_msg_size) < 0) {
fprintf(stderr, "%s\n", err_msg);
exit(-1);
}
if (convert_oauth_key_data(&okd_array[1], &okey_array[1], err_msg, err_msg_size) < 0) {
fprintf(stderr, "%s\n", err_msg);
exit(-1);
}
if (convert_oauth_key_data(&okd_array[2], &okey_array[2], err_msg, err_msg_size) < 0) {
fprintf(stderr, "%s\n", err_msg);
exit(-1);
}
}
break;
case 'a':
bps = (band_limit_t)strtoul(optarg,NULL,10);
break;
case 'o':
STRCPY(origin,optarg);
break;
case 'B':
random_disconnect = 1;
break;
case 'G':
extra_requests = 1;
break;
case 'F':
STRCPY(cipher_suite,optarg);
break;
case 'I':
no_permissions = 1;
break;
case 'M':
mobility = 1;
break;
case 'E':
{
char* fn = find_config_file(optarg,1);
if(!fn) {
fprintf(stderr,"ERROR: file %s not found\n",optarg);
exit(-1);
}
STRCPY(ca_cert_file,fn);
}
break;
case 'O':
dos = 1;
break;
case 'C':
rest_api_separator=*optarg;
break;
case 'D':
mandatory_channel_padding = 1;
break;
case 'N':
negative_test = 1;
break;
case 'R':
negative_protocol_test = 1;
break;
case 'z':
RTP_PACKET_INTERVAL = atoi(optarg);
break;
case 'Z':
dual_allocation = 1;
break;
case 'u':
STRCPY(g_uname, optarg);
break;
case 'w':
STRCPY(g_upwd, optarg);
break;
case 'g':
dont_fragment = 1;
break;
case 'd':
STRCPY(client_ifname, optarg);
break;
case 'x':
default_address_family = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6;
break;
case 'X':
default_address_family = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4;
break;
case 'l':
clmessage_length = atoi(optarg);
break;
case 's':
do_not_use_channel = 1;
break;
case 'n':
messagenumber = atoi(optarg);
break;
case 'p':
port = atoi(optarg);
break;
case 'L':
STRCPY(local_addr, optarg);
break;
case 'e':
STRCPY(peer_address, optarg);
break;
case 'r':
peer_port = atoi(optarg);
break;
case 'v':
clnet_verbose = TURN_VERBOSE_NORMAL;
break;
case 'h':
hang_on = 1;
break;
case 'c':
no_rtcp = 1;
break;
case 'm':
mclient = atoi(optarg);
break;
case 'y':
c2c = 1;
break;
case 't':
use_tcp = 1;
break;
case 'b':
use_sctp = 1;
use_tcp = 1;
break;
case 'P':
passive_tcp = 1;
/* implies 'T': */
/* no break */
/* Falls through. */
case 'T':
relay_transport = STUN_ATTRIBUTE_TRANSPORT_TCP_VALUE;
break;
case 'U':
use_null_cipher = 1;
/* implies 'S' */
/* no break */
/* Falls through. */
case 'S':
use_secure = 1;
break;
case 'W':
g_use_auth_secret_with_timestamp = 1;
STRCPY(g_auth_secret,optarg);
break;
case 'i':
{
char* fn = find_config_file(optarg,1);
if(!fn) {
fprintf(stderr,"ERROR: file %s not found\n",optarg);
exit(-1);
}
STRCPY(cert_file,fn);
free(fn);
}
break;
case 'k':
{
char* fn = find_config_file(optarg,1);
if(!fn) {
fprintf(stderr,"ERROR: file %s not found\n",optarg);
exit(-1);
}
STRCPY(pkey_file,fn);
free(fn);
}
break;
default:
fprintf(stderr, "%s\n", Usage);
exit(1);
}
}
if (convert_oauth_key_data(&okd_array[2], &okey_array[2], err_msg, err_msg_size) < 0) {
fprintf(stderr, "%s\n", err_msg);
exit(-1);
}
} break;
case 'a':
bps = (band_limit_t)strtoul(optarg, NULL, 10);
break;
case 'o':
STRCPY(origin, optarg);
break;
case 'B':
random_disconnect = 1;
break;
case 'G':
extra_requests = 1;
break;
case 'F':
STRCPY(cipher_suite, optarg);
break;
case 'I':
no_permissions = 1;
break;
case 'M':
mobility = 1;
break;
case 'E': {
char *fn = find_config_file(optarg, 1);
if (!fn) {
fprintf(stderr, "ERROR: file %s not found\n", optarg);
exit(-1);
}
STRCPY(ca_cert_file, fn);
} break;
case 'O':
dos = 1;
break;
case 'C':
rest_api_separator = *optarg;
break;
case 'D':
mandatory_channel_padding = 1;
break;
case 'N':
negative_test = 1;
break;
case 'R':
negative_protocol_test = 1;
break;
case 'z':
RTP_PACKET_INTERVAL = atoi(optarg);
break;
case 'Z':
dual_allocation = 1;
break;
case 'u':
STRCPY(g_uname, optarg);
break;
case 'w':
STRCPY(g_upwd, optarg);
break;
case 'g':
dont_fragment = 1;
break;
case 'd':
STRCPY(client_ifname, optarg);
break;
case 'x':
default_address_family = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6;
break;
case 'X':
default_address_family = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4;
break;
case 'l':
clmessage_length = atoi(optarg);
break;
case 's':
do_not_use_channel = 1;
break;
case 'n':
messagenumber = atoi(optarg);
break;
case 'p':
port = atoi(optarg);
break;
case 'L':
STRCPY(local_addr, optarg);
break;
case 'e':
STRCPY(peer_address, optarg);
break;
case 'r':
peer_port = atoi(optarg);
break;
case 'v':
clnet_verbose = TURN_VERBOSE_NORMAL;
break;
case 'h':
hang_on = 1;
break;
case 'c':
no_rtcp = 1;
break;
case 'm':
mclient = atoi(optarg);
break;
case 'y':
c2c = 1;
break;
case 't':
use_tcp = 1;
break;
case 'b':
use_sctp = 1;
use_tcp = 1;
break;
case 'P':
passive_tcp = 1;
/* implies 'T': */
/* no break */
/* Falls through. */
case 'T':
relay_transport = STUN_ATTRIBUTE_TRANSPORT_TCP_VALUE;
break;
case 'U':
use_null_cipher = 1;
/* implies 'S' */
/* no break */
/* Falls through. */
case 'S':
use_secure = 1;
break;
case 'W':
g_use_auth_secret_with_timestamp = 1;
STRCPY(g_auth_secret, optarg);
break;
case 'i': {
char *fn = find_config_file(optarg, 1);
if (!fn) {
fprintf(stderr, "ERROR: file %s not found\n", optarg);
exit(-1);
}
STRCPY(cert_file, fn);
free(fn);
} break;
case 'k': {
char *fn = find_config_file(optarg, 1);
if (!fn) {
fprintf(stderr, "ERROR: file %s not found\n", optarg);
exit(-1);
}
STRCPY(pkey_file, fn);
free(fn);
} break;
default:
fprintf(stderr, "%s\n", Usage);
exit(1);
}
}
if(dual_allocation) {
no_rtcp = 1;
}
if (dual_allocation) {
no_rtcp = 1;
}
if(g_use_auth_secret_with_timestamp) {
if (g_use_auth_secret_with_timestamp) {
{
char new_uname[1025];
const unsigned long exp_time = 3600 * 24; /* one day */
if(g_uname[0]) {
snprintf(new_uname,sizeof(new_uname),"%lu%c%s",(unsigned long)time(NULL) + exp_time,rest_api_separator, (char*)g_uname);
} else {
snprintf(new_uname,sizeof(new_uname),"%lu", (unsigned long)time(NULL) + exp_time);
}
STRCPY(g_uname,new_uname);
}
{
uint8_t hmac[MAXSHASIZE];
unsigned int hmac_len;
{
char new_uname[1025];
const unsigned long exp_time = 3600 * 24; /* one day */
if (g_uname[0]) {
snprintf(new_uname, sizeof(new_uname), "%lu%c%s", (unsigned long)time(NULL) + exp_time, rest_api_separator,
(char *)g_uname);
} else {
snprintf(new_uname, sizeof(new_uname), "%lu", (unsigned long)time(NULL) + exp_time);
}
STRCPY(g_uname, new_uname);
}
{
uint8_t hmac[MAXSHASIZE];
unsigned int hmac_len;
switch(shatype) {
case SHATYPE_SHA256:
hmac_len = SHA256SIZEBYTES;
break;
case SHATYPE_SHA384:
hmac_len = SHA384SIZEBYTES;
break;
case SHATYPE_SHA512:
hmac_len = SHA512SIZEBYTES;
break;
default:
hmac_len = SHA1SIZEBYTES;
};
switch (shatype) {
case SHATYPE_SHA256:
hmac_len = SHA256SIZEBYTES;
break;
case SHATYPE_SHA384:
hmac_len = SHA384SIZEBYTES;
break;
case SHATYPE_SHA512:
hmac_len = SHA512SIZEBYTES;
break;
default:
hmac_len = SHA1SIZEBYTES;
};
hmac[0]=0;
hmac[0] = 0;
if(stun_calculate_hmac(g_uname, strlen((char*)g_uname), (uint8_t*)g_auth_secret, strlen(g_auth_secret), hmac, &hmac_len, shatype)>=0) {
size_t pwd_length = 0;
char *pwd = base64_encode(hmac,hmac_len,&pwd_length);
if (stun_calculate_hmac(g_uname, strlen((char *)g_uname), (uint8_t *)g_auth_secret, strlen(g_auth_secret), hmac,
&hmac_len, shatype) >= 0) {
size_t pwd_length = 0;
char *pwd = base64_encode(hmac, hmac_len, &pwd_length);
if(pwd) {
if(pwd_length>0) {
memcpy(g_upwd,pwd,pwd_length);
g_upwd[pwd_length]=0;
}
}
free(pwd);
}
}
}
if (pwd) {
if (pwd_length > 0) {
memcpy(g_upwd, pwd, pwd_length);
g_upwd[pwd_length] = 0;
}
}
free(pwd);
}
}
}
if(is_TCP_relay()) {
dont_fragment = 0;
no_rtcp = 1;
c2c = 1;
use_tcp = 1;
do_not_use_channel = 1;
}
if (is_TCP_relay()) {
dont_fragment = 0;
no_rtcp = 1;
c2c = 1;
use_tcp = 1;
do_not_use_channel = 1;
}
if(port == 0) {
if(use_secure)
port = DEFAULT_STUN_TLS_PORT;
else
port = DEFAULT_STUN_PORT;
}
if (port == 0) {
if (use_secure)
port = DEFAULT_STUN_TLS_PORT;
else
port = DEFAULT_STUN_PORT;
}
if (clmessage_length < (int) sizeof(message_info))
clmessage_length = (int) sizeof(message_info);
if (clmessage_length < (int)sizeof(message_info))
clmessage_length = (int)sizeof(message_info);
const int max_header = 100;
if(clmessage_length > (int)(STUN_BUFFER_SIZE-max_header)) {
fprintf(stderr,"Message length was corrected to %d\n",(STUN_BUFFER_SIZE-max_header));
clmessage_length = (int)(STUN_BUFFER_SIZE-max_header);
}
const int max_header = 100;
if (clmessage_length > (int)(STUN_BUFFER_SIZE - max_header)) {
fprintf(stderr, "Message length was corrected to %d\n", (STUN_BUFFER_SIZE - max_header));
clmessage_length = (int)(STUN_BUFFER_SIZE - max_header);
}
if (optind >= argc) {
fprintf(stderr, "%s\n", Usage);
exit(-1);
}
if (optind >= argc) {
fprintf(stderr, "%s\n", Usage);
exit(-1);
}
if (!c2c) {
if(!peer_address[0]) {
fprintf(stderr,"Either -e peer_address or -y must be specified\n");
return -1;
}
if (!c2c) {
if (!peer_address[0]) {
fprintf(stderr, "Either -e peer_address or -y must be specified\n");
return -1;
}
if (make_ioa_addr((const uint8_t*) peer_address, peer_port, &peer_addr) < 0) {
return -1;
}
if (make_ioa_addr((const uint8_t *)peer_address, peer_port, &peer_addr) < 0) {
return -1;
}
if(peer_addr.ss.sa_family == AF_INET6) {
default_address_family = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6;
} else if(peer_addr.ss.sa_family == AF_INET) {
default_address_family = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4;
}
if (peer_addr.ss.sa_family == AF_INET6) {
default_address_family = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6;
} else if (peer_addr.ss.sa_family == AF_INET) {
default_address_family = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4;
}
}
}
/* SSL Init ==>> */
/* SSL Init ==>> */
if (use_secure) {
if(use_secure) {
SSL_load_error_strings();
OpenSSL_add_ssl_algorithms();
SSL_load_error_strings();
OpenSSL_add_ssl_algorithms();
const char *csuite = "ALL"; //"AES256-SHA" "DH"
if (use_null_cipher)
csuite = "eNULL";
else if (cipher_suite[0])
csuite = cipher_suite;
const char *csuite = "ALL"; //"AES256-SHA" "DH"
if(use_null_cipher)
csuite = "eNULL";
else if(cipher_suite[0])
csuite=cipher_suite;
if(use_tcp) {
if (use_tcp) {
#if OPENSSL_VERSION_NUMBER < 0x10100000L
#if TLSv1_2_SUPPORTED
root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(TLSv1_2_client_method());
#elif TLSv1_1_SUPPORTED
root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(TLSv1_1_client_method());
#else
root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(TLSv1_client_method());
#endif
SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite);
#else // OPENSSL_VERSION_NUMBER >= 0x10100000L
root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(TLS_client_method());
SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite);
#if TLSv1_2_SUPPORTED
root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(TLSv1_2_client_method());
#elif TLSv1_1_SUPPORTED
root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(TLSv1_1_client_method());
#else
root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(TLSv1_client_method());
#endif
root_tls_ctx_num++;
} else {
SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite);
#else // OPENSSL_VERSION_NUMBER >= 0x10100000L
root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(TLS_client_method());
SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite);
#endif
root_tls_ctx_num++;
} else {
#if !DTLS_SUPPORTED
fprintf(stderr,"ERROR: DTLS is not supported.\n");
exit(-1);
fprintf(stderr, "ERROR: DTLS is not supported.\n");
exit(-1);
#else
#if OPENSSL_VERSION_NUMBER < 0x10100000L
if(OPENSSL_VERSION_NUMBER < 0x10000000L) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "WARNING: OpenSSL version is rather old, DTLS may not be working correctly.\n");
}
#if DTLSv1_2_SUPPORTED
root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(DTLSv1_2_client_method());
#else
root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(DTLSv1_client_method());
#endif
SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite);
if (OPENSSL_VERSION_NUMBER < 0x10000000L) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING,
"WARNING: OpenSSL version is rather old, DTLS may not be working correctly.\n");
}
#if DTLSv1_2_SUPPORTED
root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(DTLSv1_2_client_method());
#else
root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(DTLSv1_client_method());
#endif
SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite);
#else // OPENSSL_VERSION_NUMBER >= 0x10100000L
root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(DTLS_client_method());
SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite);
root_tls_ctx[root_tls_ctx_num] = SSL_CTX_new(DTLS_client_method());
SSL_CTX_set_cipher_list(root_tls_ctx[root_tls_ctx_num], csuite);
#endif
#endif
root_tls_ctx_num++;
}
}
root_tls_ctx_num++;
}
}
int use_cert = 0;
int use_ca_cert = 0;
if(cert_file[0] && pkey_file[0])
{
use_cert = 1;
}
if(ca_cert_file[0])
{
use_ca_cert = 1;
}
int use_cert = 0;
int use_ca_cert = 0;
if (cert_file[0] && pkey_file[0]) {
use_cert = 1;
}
if (ca_cert_file[0]) {
use_ca_cert = 1;
}
if(use_cert)
{
int sslind = 0;
for(sslind = 0; sslind<root_tls_ctx_num; sslind++)
{
if (!SSL_CTX_use_certificate_chain_file(root_tls_ctx[sslind], cert_file)) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "\nERROR: could not load certificate chain file!\n");
exit(-1);
}
if (use_cert) {
int sslind = 0;
for (sslind = 0; sslind < root_tls_ctx_num; sslind++) {
if (!SSL_CTX_use_certificate_chain_file(root_tls_ctx[sslind], cert_file)) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "\nERROR: could not load certificate chain file!\n");
exit(-1);
}
if (!SSL_CTX_use_PrivateKey_file(root_tls_ctx[sslind], pkey_file,
SSL_FILETYPE_PEM)) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "\nERROR: could not load private key file!\n");
exit(-1);
}
if (!SSL_CTX_use_PrivateKey_file(root_tls_ctx[sslind], pkey_file, SSL_FILETYPE_PEM)) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "\nERROR: could not load private key file!\n");
exit(-1);
}
if (!SSL_CTX_check_private_key(root_tls_ctx[sslind])) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "\nERROR: invalid private key!\n");
exit(-1);
}
if (!SSL_CTX_check_private_key(root_tls_ctx[sslind])) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "\nERROR: invalid private key!\n");
exit(-1);
}
if (use_ca_cert)
{
if (!SSL_CTX_load_verify_locations(root_tls_ctx[sslind], ca_cert_file, NULL )) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,
"ERROR: cannot load CA from file: %s\n",
ca_cert_file);
exit(-1);
}
if (use_ca_cert) {
if (!SSL_CTX_load_verify_locations(root_tls_ctx[sslind], ca_cert_file, NULL)) {
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "ERROR: cannot load CA from file: %s\n", ca_cert_file);
exit(-1);
}
/* Set to require peer (client) certificate verification */
SSL_CTX_set_verify(root_tls_ctx[sslind], SSL_VERIFY_PEER, NULL );
/* Set to require peer (client) certificate verification */
SSL_CTX_set_verify(root_tls_ctx[sslind], SSL_VERIFY_PEER, NULL);
/* Set the verification depth to 9 */
SSL_CTX_set_verify_depth(root_tls_ctx[sslind], 9);
}
else
{
SSL_CTX_set_verify(root_tls_ctx[sslind], SSL_VERIFY_NONE, NULL );
}
}
}
/* Set the verification depth to 9 */
SSL_CTX_set_verify_depth(root_tls_ctx[sslind], 9);
} else {
SSL_CTX_set_verify(root_tls_ctx[sslind], SSL_VERIFY_NONE, NULL);
}
}
}
start_mclient(argv[optind], port, client_ifname, local_addr, messagenumber, mclient);
start_mclient(argv[optind], port, client_ifname, local_addr, messagenumber, mclient);
return 0;
return 0;
}

View File

@ -31,14 +31,14 @@
#ifndef __SESSION__
#define __SESSION__
#include <event2/event.h>
#include <event2/bufferevent.h>
#include <event2/event.h>
#include "ns_turn_ioaddr.h"
#include "ns_turn_utils.h"
#include "stun_buffer.h"
#include "apputils.h"
#include "stun_buffer.h"
#include "ns_turn_openssl.h"
@ -48,29 +48,24 @@ extern "C" {
///////// types ////////////
enum _UR_STATE {
UR_STATE_UNKNOWN=0,
UR_STATE_READY,
UR_STATE_DONE
};
enum _UR_STATE { UR_STATE_UNKNOWN = 0, UR_STATE_READY, UR_STATE_DONE };
typedef enum _UR_STATE UR_STATE;
//////////////// session info //////////////////////
typedef struct
{
/* RFC 6062 */
uint32_t cid;
ioa_addr tcp_data_local_addr;
ioa_socket_raw tcp_data_fd;
SSL *tcp_data_ssl;
int tcp_data_bound;
typedef struct {
/* RFC 6062 */
uint32_t cid;
ioa_addr tcp_data_local_addr;
ioa_socket_raw tcp_data_fd;
SSL *tcp_data_ssl;
int tcp_data_bound;
} app_tcp_conn_info;
typedef struct {
ioa_addr local_addr;
char lsaddr[129];
char lsaddr[129];
ioa_addr remote_addr;
char rsaddr[129];
char ifname[129];
@ -79,11 +74,11 @@ typedef struct {
ioa_socket_raw fd;
SSL *ssl;
int broken;
uint8_t nonce[STUN_MAX_NONCE_SIZE+1];
uint8_t realm[STUN_MAX_REALM_SIZE+1];
uint8_t nonce[STUN_MAX_NONCE_SIZE + 1];
uint8_t realm[STUN_MAX_REALM_SIZE + 1];
/* oAuth */
int oauth;
uint8_t server_name[STUN_MAX_SERVER_NAME_SIZE+1];
uint8_t server_name[STUN_MAX_SERVER_NAME_SIZE + 1];
hmackey_t key;
int key_set;
int cok;
@ -108,14 +103,14 @@ typedef struct {
stun_buffer out_buffer;
uint32_t refresh_time;
uint32_t finished_time;
//Msg counters:
// Msg counters:
int tot_msgnum;
int wmsgnum;
int rmsgnum;
int recvmsgnum;
uint32_t recvtimems;
uint32_t to_send_timems;
//Statistics:
// Statistics:
size_t loss;
uint64_t latency;
uint64_t jitter;
@ -124,8 +119,8 @@ typedef struct {
///////////////////////////////////////////////////////
typedef struct _message_info {
int msgnum;
uint64_t mstime;
int msgnum;
uint64_t mstime;
} message_info;
///////////////////////////////////////////////////////////////////////////////

File diff suppressed because it is too large Load Diff

View File

@ -45,29 +45,16 @@ int not_rare_event(void);
void add_origin(stun_buffer *message);
int start_c2c_connection(uint16_t clnet_remote_port,
const char *remote_address,
const unsigned char* ifname, const char *local_address,
int verbose,
app_ur_conn_info *clnet_info_probe,
app_ur_conn_info *clnet_info1,
uint16_t *chn1,
app_ur_conn_info *clnet_info1_rtcp,
uint16_t *chn1_rtcp,
app_ur_conn_info *clnet_info2,
uint16_t *chn2,
app_ur_conn_info *clnet_info2_rtcp,
uint16_t *chn2_rtcp);
int start_c2c_connection(uint16_t clnet_remote_port, const char *remote_address, const unsigned char *ifname,
const char *local_address, int verbose, app_ur_conn_info *clnet_info_probe,
app_ur_conn_info *clnet_info1, uint16_t *chn1, app_ur_conn_info *clnet_info1_rtcp,
uint16_t *chn1_rtcp, app_ur_conn_info *clnet_info2, uint16_t *chn2,
app_ur_conn_info *clnet_info2_rtcp, uint16_t *chn2_rtcp);
int start_connection(uint16_t clnet_remote_port,
const char *remote_address,
const unsigned char* ifname, const char *local_address,
int verbose,
app_ur_conn_info *clnet_info_probe,
app_ur_conn_info *clnet_info,
uint16_t *chn,
app_ur_conn_info *clnet_info_rtcp,
uint16_t *chn_rtcp);
int start_connection(uint16_t clnet_remote_port, const char *remote_address, const unsigned char *ifname,
const char *local_address, int verbose, app_ur_conn_info *clnet_info_probe,
app_ur_conn_info *clnet_info, uint16_t *chn, app_ur_conn_info *clnet_info_rtcp,
uint16_t *chn_rtcp);
int turn_tcp_connect(int verbose, app_ur_conn_info *clnet_info, ioa_addr *peer_addr);
@ -84,4 +71,3 @@ int read_mobility_ticket(app_ur_conn_info *clnet_info, stun_buffer *message);
#endif
#endif //__STARTCLIENT_TURN__

File diff suppressed because it is too large Load Diff

View File

@ -32,8 +32,8 @@
#define __UCLIENT_ECHO__
#include "ns_turn_utils.h"
#include "stun_buffer.h"
#include "session.h"
#include "stun_buffer.h"
#include "ns_turn_openssl.h"
@ -60,7 +60,7 @@ extern ioa_addr peer_addr;
extern int no_rtcp;
extern int default_address_family;
extern int dont_fragment;
extern uint8_t g_uname[STUN_MAX_USERNAME_SIZE+1];
extern uint8_t g_uname[STUN_MAX_USERNAME_SIZE + 1];
extern password_t g_upwd;
extern char g_auth_secret[1025];
extern int g_use_auth_secret_with_timestamp;
@ -70,7 +70,7 @@ extern int root_tls_ctx_num;
extern int RTP_PACKET_INTERVAL;
extern uint8_t relay_transport;
extern unsigned char client_ifname[1025];
extern struct event_base* client_event_base;
extern struct event_base *client_event_base;
extern int passive_tcp;
extern int mandatory_channel_padding;
extern int negative_test;
@ -84,7 +84,7 @@ extern int extra_requests;
extern band_limit_t bps;
extern int dual_allocation;
extern char origin[STUN_MAX_ORIGIN_SIZE+1];
extern char origin[STUN_MAX_ORIGIN_SIZE + 1];
extern int oauth;
extern oauth_key okey_array[3];
@ -94,14 +94,14 @@ extern oauth_key okey_array[3];
#define is_TCP_relay() (relay_transport == STUN_ATTRIBUTE_TRANSPORT_TCP_VALUE)
void start_mclient(const char *remote_address, int port,
const unsigned char* ifname, const char *local_address,
int messagenumber, int mclient);
void start_mclient(const char *remote_address, int port, const unsigned char *ifname, const char *local_address,
int messagenumber, int mclient);
int send_buffer(app_ur_conn_info *clnet_info, stun_buffer* message, int data_connection, app_tcp_conn_info *atc);
int recv_buffer(app_ur_conn_info *clnet_info, stun_buffer* message, int sync, int data_connection, app_tcp_conn_info *atc, stun_buffer* request_message);
int send_buffer(app_ur_conn_info *clnet_info, stun_buffer *message, int data_connection, app_tcp_conn_info *atc);
int recv_buffer(app_ur_conn_info *clnet_info, stun_buffer *message, int sync, int data_connection,
app_tcp_conn_info *atc, stun_buffer *request_message);
void client_input_handler(evutil_socket_t fd, short what, void* arg);
void client_input_handler(evutil_socket_t fd, short what, void *arg);
turn_credential_type get_turn_credentials_type(void);
@ -117,4 +117,3 @@ SOCKET_TYPE get_socket_type(void);
#endif
#endif //__UCLIENT_ECHO__

File diff suppressed because it is too large Load Diff

View File

@ -31,133 +31,136 @@
#include "ns_turn_ioaddr.h"
#if defined(__unix__) || defined(unix) || defined(__APPLE__)
#include <netdb.h>
#include <netdb.h>
#endif
//////////////////////////////////////////////////////////////
uint32_t get_ioa_addr_len(const ioa_addr* addr) {
if(addr->ss.sa_family == AF_INET) return sizeof(struct sockaddr_in);
else if(addr->ss.sa_family == AF_INET6) return sizeof(struct sockaddr_in6);
uint32_t get_ioa_addr_len(const ioa_addr *addr) {
if (addr->ss.sa_family == AF_INET)
return sizeof(struct sockaddr_in);
else if (addr->ss.sa_family == AF_INET6)
return sizeof(struct sockaddr_in6);
return 0;
}
///////////////////////////////////////////////////////////////
void addr_set_any(ioa_addr *addr) {
if(addr)
memset(addr, 0, sizeof(ioa_addr));
if (addr)
memset(addr, 0, sizeof(ioa_addr));
}
int addr_any(const ioa_addr* addr) {
int addr_any(const ioa_addr *addr) {
if(!addr)
return 1;
if (!addr)
return 1;
if(addr->ss.sa_family == AF_INET) {
return ((addr->s4.sin_addr.s_addr==0)&&(addr->s4.sin_port==0));
} else if(addr->ss.sa_family == AF_INET6) {
if(addr->s6.sin6_port!=0) return 0;
if (addr->ss.sa_family == AF_INET) {
return ((addr->s4.sin_addr.s_addr == 0) && (addr->s4.sin_port == 0));
} else if (addr->ss.sa_family == AF_INET6) {
if (addr->s6.sin6_port != 0)
return 0;
else {
size_t i;
for(i=0;i<sizeof(addr->s6.sin6_addr);i++)
if(((const char*)&(addr->s6.sin6_addr))[i]) return 0;
for (i = 0; i < sizeof(addr->s6.sin6_addr); i++)
if (((const char *)&(addr->s6.sin6_addr))[i])
return 0;
}
}
return 1;
}
int addr_any_no_port(const ioa_addr* addr) {
if(!addr)
return 1;
int addr_any_no_port(const ioa_addr *addr) {
if (!addr)
return 1;
if(addr->ss.sa_family == AF_INET) {
return (addr->s4.sin_addr.s_addr==0);
} else if(addr->ss.sa_family == AF_INET6) {
if (addr->ss.sa_family == AF_INET) {
return (addr->s4.sin_addr.s_addr == 0);
} else if (addr->ss.sa_family == AF_INET6) {
size_t i;
for(i=0;i<sizeof(addr->s6.sin6_addr);i++)
if(((const char*)(&(addr->s6.sin6_addr)))[i]) return 0;
for (i = 0; i < sizeof(addr->s6.sin6_addr); i++)
if (((const char *)(&(addr->s6.sin6_addr)))[i])
return 0;
}
return 1;
}
uint32_t hash_int32(uint32_t a)
{
a = a ^ (a>>4);
a = (a^0xdeadbeef) + (a<<5);
a = a ^ (a>>11);
return a;
uint32_t hash_int32(uint32_t a) {
a = a ^ (a >> 4);
a = (a ^ 0xdeadbeef) + (a << 5);
a = a ^ (a >> 11);
return a;
}
uint64_t hash_int64(uint64_t a)
{
a = a ^ (a>>4);
a = (a^0xdeadbeefdeadbeefLL) + (a<<5);
a = a ^ (a>>11);
return a;
uint64_t hash_int64(uint64_t a) {
a = a ^ (a >> 4);
a = (a ^ 0xdeadbeefdeadbeefLL) + (a << 5);
a = a ^ (a >> 11);
return a;
}
uint32_t addr_hash(const ioa_addr *addr)
{
if(!addr)
return 0;
uint32_t addr_hash(const ioa_addr *addr) {
if (!addr)
return 0;
uint32_t ret = 0;
if (addr->ss.sa_family == AF_INET) {
ret = hash_int32(addr->s4.sin_addr.s_addr + addr->s4.sin_port);
} else {
uint64_t a[2];
memcpy(&a, &(addr->s6.sin6_addr), sizeof(a));
ret = (uint32_t)((hash_int64(a[0])<<3) + (hash_int64(a[1] + addr->s6.sin6_port)));
}
return ret;
uint32_t ret = 0;
if (addr->ss.sa_family == AF_INET) {
ret = hash_int32(addr->s4.sin_addr.s_addr + addr->s4.sin_port);
} else {
uint64_t a[2];
memcpy(&a, &(addr->s6.sin6_addr), sizeof(a));
ret = (uint32_t)((hash_int64(a[0]) << 3) + (hash_int64(a[1] + addr->s6.sin6_port)));
}
return ret;
}
uint32_t addr_hash_no_port(const ioa_addr *addr)
{
if(!addr)
return 0;
uint32_t addr_hash_no_port(const ioa_addr *addr) {
if (!addr)
return 0;
uint32_t ret = 0;
if (addr->ss.sa_family == AF_INET) {
ret = hash_int32(addr->s4.sin_addr.s_addr);
} else {
uint64_t a[2];
memcpy(&a, &(addr->s6.sin6_addr), sizeof(a));
ret = (uint32_t)((hash_int64(a[0])<<3) + (hash_int64(a[1])));
}
return ret;
uint32_t ret = 0;
if (addr->ss.sa_family == AF_INET) {
ret = hash_int32(addr->s4.sin_addr.s_addr);
} else {
uint64_t a[2];
memcpy(&a, &(addr->s6.sin6_addr), sizeof(a));
ret = (uint32_t)((hash_int64(a[0]) << 3) + (hash_int64(a[1])));
}
return ret;
}
void addr_cpy(ioa_addr* dst, const ioa_addr* src) {
if(dst && src)
memcpy(dst,src,sizeof(ioa_addr));
void addr_cpy(ioa_addr *dst, const ioa_addr *src) {
if (dst && src)
memcpy(dst, src, sizeof(ioa_addr));
}
void addr_cpy4(ioa_addr* dst, const struct sockaddr_in* src) {
if(src && dst)
memcpy(dst,src,sizeof(struct sockaddr_in));
void addr_cpy4(ioa_addr *dst, const struct sockaddr_in *src) {
if (src && dst)
memcpy(dst, src, sizeof(struct sockaddr_in));
}
void addr_cpy6(ioa_addr* dst, const struct sockaddr_in6* src) {
if(src && dst)
memcpy(dst,src,sizeof(struct sockaddr_in6));
void addr_cpy6(ioa_addr *dst, const struct sockaddr_in6 *src) {
if (src && dst)
memcpy(dst, src, sizeof(struct sockaddr_in6));
}
int addr_eq(const ioa_addr* a1, const ioa_addr *a2) {
int addr_eq(const ioa_addr *a1, const ioa_addr *a2) {
if(!a1) return (!a2);
else if(!a2) return (!a1);
if (!a1)
return (!a2);
else if (!a2)
return (!a1);
if(a1->ss.sa_family == a2->ss.sa_family) {
if(a1->ss.sa_family == AF_INET && a1->s4.sin_port == a2->s4.sin_port) {
if((int)a1->s4.sin_addr.s_addr == (int)a2->s4.sin_addr.s_addr) {
return 1;
if (a1->ss.sa_family == a2->ss.sa_family) {
if (a1->ss.sa_family == AF_INET && a1->s4.sin_port == a2->s4.sin_port) {
if ((int)a1->s4.sin_addr.s_addr == (int)a2->s4.sin_addr.s_addr) {
return 1;
}
} else if(a1->ss.sa_family == AF_INET6 && a1->s6.sin6_port == a2->s6.sin6_port) {
if( memcmp(&(a1->s6.sin6_addr), &(a2->s6.sin6_addr) ,sizeof(struct in6_addr)) == 0 ) {
} else if (a1->ss.sa_family == AF_INET6 && a1->s6.sin6_port == a2->s6.sin6_port) {
if (memcmp(&(a1->s6.sin6_addr), &(a2->s6.sin6_addr), sizeof(struct in6_addr)) == 0) {
return 1;
}
}
@ -166,18 +169,20 @@ int addr_eq(const ioa_addr* a1, const ioa_addr *a2) {
return 0;
}
int addr_eq_no_port(const ioa_addr* a1, const ioa_addr *a2) {
int addr_eq_no_port(const ioa_addr *a1, const ioa_addr *a2) {
if(!a1) return (!a2);
else if(!a2) return (!a1);
if(a1->ss.sa_family == a2->ss.sa_family) {
if(a1->ss.sa_family == AF_INET) {
if((int)a1->s4.sin_addr.s_addr == (int)a2->s4.sin_addr.s_addr) {
return 1;
if (!a1)
return (!a2);
else if (!a2)
return (!a1);
if (a1->ss.sa_family == a2->ss.sa_family) {
if (a1->ss.sa_family == AF_INET) {
if ((int)a1->s4.sin_addr.s_addr == (int)a2->s4.sin_addr.s_addr) {
return 1;
}
} else if(a1->ss.sa_family == AF_INET6) {
if( memcmp(&(a1->s6.sin6_addr), &(a2->s6.sin6_addr) ,sizeof(struct in6_addr)) == 0 ) {
} else if (a1->ss.sa_family == AF_INET6) {
if (memcmp(&(a1->s6.sin6_addr), &(a2->s6.sin6_addr), sizeof(struct in6_addr)) == 0) {
return 1;
}
}
@ -185,29 +190,30 @@ int addr_eq_no_port(const ioa_addr* a1, const ioa_addr *a2) {
return 0;
}
int make_ioa_addr(const uint8_t* saddr0, int port, ioa_addr *addr) {
int make_ioa_addr(const uint8_t *saddr0, int port, ioa_addr *addr) {
if(!saddr0 || !addr) return -1;
if (!saddr0 || !addr)
return -1;
char ssaddr[257];
STRCPY(ssaddr,saddr0);
STRCPY(ssaddr, saddr0);
char* saddr=ssaddr;
while(*saddr == ' ') ++saddr;
char *saddr = ssaddr;
while (*saddr == ' ')
++saddr;
size_t len=strlen(saddr);
while(len>0) {
if(saddr[len-1]==' ') {
saddr[len-1]=0;
--len;
} else {
break;
}
size_t len = strlen(saddr);
while (len > 0) {
if (saddr[len - 1] == ' ') {
saddr[len - 1] = 0;
--len;
} else {
break;
}
}
memset(addr, 0, sizeof(ioa_addr));
if((len == 0)||
(inet_pton(AF_INET, saddr, &addr->s4.sin_addr) == 1)) {
if ((len == 0) || (inet_pton(AF_INET, saddr, &addr->s4.sin_addr) == 1)) {
addr->s4.sin_family = AF_INET;
#if defined(TURN_HAS_SIN_LEN) /* tested when configured */
addr->s4.sin_len = sizeof(struct sockaddr_in);
@ -234,176 +240,174 @@ int make_ioa_addr(const uint8_t* saddr0, int port, ioa_addr *addr) {
addr_hints.ai_next = NULL;
err = getaddrinfo(saddr, NULL, &addr_hints, &addr_result);
if ((err != 0)||(!addr_result)) {
fprintf(stderr,"error resolving '%s' hostname: %s\n",saddr,gai_strerror(err));
if ((err != 0) || (!addr_result)) {
fprintf(stderr, "error resolving '%s' hostname: %s\n", saddr, gai_strerror(err));
return -1;
}
int family = AF_INET;
struct addrinfo *addr_result_orig = addr_result;
int found = 0;
beg_af:
beg_af:
while(addr_result) {
while (addr_result) {
if(addr_result->ai_family == family) {
if (addr_result->ai_family == AF_INET) {
memcpy(addr, addr_result->ai_addr, addr_result->ai_addrlen);
addr->s4.sin_port = nswap16(port);
if (addr_result->ai_family == family) {
if (addr_result->ai_family == AF_INET) {
memcpy(addr, addr_result->ai_addr, addr_result->ai_addrlen);
addr->s4.sin_port = nswap16(port);
#if defined(TURN_HAS_SIN_LEN) /* tested when configured */
addr->s4.sin_len = sizeof(struct sockaddr_in);
addr->s4.sin_len = sizeof(struct sockaddr_in);
#endif
found = 1;
break;
} else if (addr_result->ai_family == AF_INET6) {
memcpy(addr, addr_result->ai_addr, addr_result->ai_addrlen);
addr->s6.sin6_port = nswap16(port);
found = 1;
break;
} else if (addr_result->ai_family == AF_INET6) {
memcpy(addr, addr_result->ai_addr, addr_result->ai_addrlen);
addr->s6.sin6_port = nswap16(port);
#if defined(SIN6_LEN) /* this define is required by IPv6 if used */
addr->s6.sin6_len = sizeof(struct sockaddr_in6);
addr->s6.sin6_len = sizeof(struct sockaddr_in6);
#endif
found = 1;
break;
}
}
found = 1;
break;
}
}
addr_result = addr_result->ai_next;
addr_result = addr_result->ai_next;
}
if(!found && family == AF_INET) {
family = AF_INET6;
addr_result = addr_result_orig;
goto beg_af;
if (!found && family == AF_INET) {
family = AF_INET6;
addr_result = addr_result_orig;
goto beg_af;
}
freeaddrinfo(addr_result_orig);
}
return 0;
}
static char* get_addr_string_and_port(char* s0, int *port)
{
char *s = s0;
while(*s && (*s==' ')) ++s;
if(*s == '[') {
++s;
char *tail = strstr(s,"]");
if(tail) {
*tail=0;
++tail;
while(*tail && (*tail==' ')) ++tail;
if(*tail==':') {
++tail;
*port = atoi(tail);
return s;
} else if(*tail == 0) {
*port = 0;
return s;
}
}
} else {
char *tail = strstr(s,":");
if(tail) {
*tail = 0;
++tail;
*port = atoi(tail);
return s;
} else {
*port = 0;
return s;
}
}
return NULL;
static char *get_addr_string_and_port(char *s0, int *port) {
char *s = s0;
while (*s && (*s == ' '))
++s;
if (*s == '[') {
++s;
char *tail = strstr(s, "]");
if (tail) {
*tail = 0;
++tail;
while (*tail && (*tail == ' '))
++tail;
if (*tail == ':') {
++tail;
*port = atoi(tail);
return s;
} else if (*tail == 0) {
*port = 0;
return s;
}
}
} else {
char *tail = strstr(s, ":");
if (tail) {
*tail = 0;
++tail;
*port = atoi(tail);
return s;
} else {
*port = 0;
return s;
}
}
return NULL;
}
int make_ioa_addr_from_full_string(const uint8_t* saddr, int default_port, ioa_addr *addr)
{
if(!addr)
return -1;
int make_ioa_addr_from_full_string(const uint8_t *saddr, int default_port, ioa_addr *addr) {
if (!addr)
return -1;
int ret = -1;
int port = 0;
char* s = strdup((const char*)saddr);
char *sa = get_addr_string_and_port(s,&port);
if(sa) {
if(port<1)
port = default_port;
ret = make_ioa_addr((uint8_t*)sa,port,addr);
}
free(s);
return ret;
int ret = -1;
int port = 0;
char *s = strdup((const char *)saddr);
char *sa = get_addr_string_and_port(s, &port);
if (sa) {
if (port < 1)
port = default_port;
ret = make_ioa_addr((uint8_t *)sa, port, addr);
}
free(s);
return ret;
}
int addr_to_string(const ioa_addr* addr, uint8_t* saddr)
{
int addr_to_string(const ioa_addr *addr, uint8_t *saddr) {
if (addr && saddr) {
if (addr && saddr) {
char addrtmp[INET6_ADDRSTRLEN];
char addrtmp[INET6_ADDRSTRLEN];
if (addr->ss.sa_family == AF_INET) {
inet_ntop(AF_INET, &addr->s4.sin_addr, addrtmp, INET_ADDRSTRLEN);
if(addr_get_port(addr)>0)
snprintf((char*)saddr, MAX_IOA_ADDR_STRING, "%s:%d", addrtmp, addr_get_port(addr));
else
strncpy((char*)saddr, addrtmp, MAX_IOA_ADDR_STRING);
} else if (addr->ss.sa_family == AF_INET6) {
inet_ntop(AF_INET6, &addr->s6.sin6_addr, addrtmp, INET6_ADDRSTRLEN);
if(addr_get_port(addr)>0)
snprintf((char*)saddr, MAX_IOA_ADDR_STRING, "[%s]:%d", addrtmp, addr_get_port(addr));
else
strncpy((char*)saddr, addrtmp, MAX_IOA_ADDR_STRING);
} else {
return -1;
}
if (addr->ss.sa_family == AF_INET) {
inet_ntop(AF_INET, &addr->s4.sin_addr, addrtmp, INET_ADDRSTRLEN);
if (addr_get_port(addr) > 0)
snprintf((char *)saddr, MAX_IOA_ADDR_STRING, "%s:%d", addrtmp, addr_get_port(addr));
else
strncpy((char *)saddr, addrtmp, MAX_IOA_ADDR_STRING);
} else if (addr->ss.sa_family == AF_INET6) {
inet_ntop(AF_INET6, &addr->s6.sin6_addr, addrtmp, INET6_ADDRSTRLEN);
if (addr_get_port(addr) > 0)
snprintf((char *)saddr, MAX_IOA_ADDR_STRING, "[%s]:%d", addrtmp, addr_get_port(addr));
else
strncpy((char *)saddr, addrtmp, MAX_IOA_ADDR_STRING);
} else {
return -1;
}
return 0;
}
return 0;
}
return -1;
return -1;
}
int addr_to_string_no_port(const ioa_addr* addr, uint8_t* saddr)
{
int addr_to_string_no_port(const ioa_addr *addr, uint8_t *saddr) {
if (addr && saddr) {
if (addr && saddr) {
char addrtmp[MAX_IOA_ADDR_STRING];
char addrtmp[MAX_IOA_ADDR_STRING];
if (addr->ss.sa_family == AF_INET) {
inet_ntop(AF_INET, &addr->s4.sin_addr, addrtmp, INET_ADDRSTRLEN);
strncpy((char*)saddr, addrtmp, MAX_IOA_ADDR_STRING);
} else if (addr->ss.sa_family == AF_INET6) {
inet_ntop(AF_INET6, &addr->s6.sin6_addr, addrtmp, INET6_ADDRSTRLEN);
strncpy((char*)saddr, addrtmp, MAX_IOA_ADDR_STRING);
} else {
return -1;
}
if (addr->ss.sa_family == AF_INET) {
inet_ntop(AF_INET, &addr->s4.sin_addr, addrtmp, INET_ADDRSTRLEN);
strncpy((char *)saddr, addrtmp, MAX_IOA_ADDR_STRING);
} else if (addr->ss.sa_family == AF_INET6) {
inet_ntop(AF_INET6, &addr->s6.sin6_addr, addrtmp, INET6_ADDRSTRLEN);
strncpy((char *)saddr, addrtmp, MAX_IOA_ADDR_STRING);
} else {
return -1;
}
return 0;
}
return 0;
}
return -1;
return -1;
}
void addr_set_port(ioa_addr* addr, int port) {
if(addr) {
if(addr->s4.sin_family == AF_INET) {
void addr_set_port(ioa_addr *addr, int port) {
if (addr) {
if (addr->s4.sin_family == AF_INET) {
addr->s4.sin_port = nswap16(port);
} else if(addr->s6.sin6_family == AF_INET6) {
} else if (addr->s6.sin6_family == AF_INET6) {
addr->s6.sin6_port = nswap16(port);
}
}
}
int addr_get_port(const ioa_addr* addr) {
if(!addr)
return 0;
int addr_get_port(const ioa_addr *addr) {
if (!addr)
return 0;
if(addr->s4.sin_family == AF_INET) {
if (addr->s4.sin_family == AF_INET) {
return nswap16(addr->s4.sin_port);
} else if(addr->s6.sin6_family == AF_INET6) {
} else if (addr->s6.sin6_family == AF_INET6) {
return nswap16(addr->s6.sin6_port);
}
return 0;
@ -411,42 +415,50 @@ int addr_get_port(const ioa_addr* addr) {
/////////////////////////////////////////////////////////////////////////////
void ioa_addr_range_set(ioa_addr_range* range, const ioa_addr* addr_min, const ioa_addr* addr_max) {
if(range) {
if(addr_min) addr_cpy(&(range->min),addr_min);
else addr_set_any(&(range->min));
if(addr_max) addr_cpy(&(range->max),addr_max);
else addr_set_any(&(range->max));
void ioa_addr_range_set(ioa_addr_range *range, const ioa_addr *addr_min, const ioa_addr *addr_max) {
if (range) {
if (addr_min)
addr_cpy(&(range->min), addr_min);
else
addr_set_any(&(range->min));
if (addr_max)
addr_cpy(&(range->max), addr_max);
else
addr_set_any(&(range->max));
}
}
int addr_less_eq(const ioa_addr* addr1, const ioa_addr* addr2) {
int addr_less_eq(const ioa_addr *addr1, const ioa_addr *addr2) {
if(!addr1) return 1;
else if(!addr2) return 0;
if (!addr1)
return 1;
else if (!addr2)
return 0;
else {
if(addr1->ss.sa_family != addr2->ss.sa_family) return (addr1->ss.sa_family < addr2->ss.sa_family);
else if(addr1->ss.sa_family == AF_INET) {
if (addr1->ss.sa_family != addr2->ss.sa_family)
return (addr1->ss.sa_family < addr2->ss.sa_family);
else if (addr1->ss.sa_family == AF_INET) {
return ((uint32_t)nswap32(addr1->s4.sin_addr.s_addr) <= (uint32_t)nswap32(addr2->s4.sin_addr.s_addr));
} else if(addr1->ss.sa_family == AF_INET6) {
} else if (addr1->ss.sa_family == AF_INET6) {
int i;
for(i=0;i<16;i++) {
if((uint8_t)(((const char*)&(addr1->s6.sin6_addr))[i]) > (uint8_t)(((const char*)&(addr2->s6.sin6_addr))[i]))
return 0;
for (i = 0; i < 16; i++) {
if ((uint8_t)(((const char *)&(addr1->s6.sin6_addr))[i]) > (uint8_t)(((const char *)&(addr2->s6.sin6_addr))[i]))
return 0;
}
return 1;
} else return 1;
} else
return 1;
}
}
int ioa_addr_in_range(const ioa_addr_range* range, const ioa_addr* addr) {
int ioa_addr_in_range(const ioa_addr_range *range, const ioa_addr *addr) {
if(range && addr) {
if(addr_any(&(range->min)) || addr_less_eq(&(range->min),addr)) {
if(addr_any(&(range->max))) {
return 1;
if (range && addr) {
if (addr_any(&(range->min)) || addr_less_eq(&(range->min), addr)) {
if (addr_any(&(range->max))) {
return 1;
} else {
return addr_less_eq(addr,&(range->max));
return addr_less_eq(addr, &(range->max));
}
}
}
@ -454,73 +466,70 @@ int ioa_addr_in_range(const ioa_addr_range* range, const ioa_addr* addr) {
return 0;
}
void ioa_addr_range_cpy(ioa_addr_range* dest, const ioa_addr_range* src) {
if(dest && src) {
addr_cpy(&(dest->min),&(src->min));
addr_cpy(&(dest->max),&(src->max));
void ioa_addr_range_cpy(ioa_addr_range *dest, const ioa_addr_range *src) {
if (dest && src) {
addr_cpy(&(dest->min), &(src->min));
addr_cpy(&(dest->max), &(src->max));
}
}
/////// Check whether this is a good address //////////////
int ioa_addr_is_multicast(ioa_addr *addr)
{
if(addr) {
if(addr->ss.sa_family == AF_INET) {
const uint8_t *u = ((const uint8_t*)&(addr->s4.sin_addr));
return (u[0] > 223);
} else if(addr->ss.sa_family == AF_INET6) {
uint8_t u = ((const uint8_t*)&(addr->s6.sin6_addr))[0];
return (u == 255);
}
}
return 0;
int ioa_addr_is_multicast(ioa_addr *addr) {
if (addr) {
if (addr->ss.sa_family == AF_INET) {
const uint8_t *u = ((const uint8_t *)&(addr->s4.sin_addr));
return (u[0] > 223);
} else if (addr->ss.sa_family == AF_INET6) {
uint8_t u = ((const uint8_t *)&(addr->s6.sin6_addr))[0];
return (u == 255);
}
}
return 0;
}
int ioa_addr_is_loopback(ioa_addr *addr)
{
if(addr) {
if(addr->ss.sa_family == AF_INET) {
const uint8_t *u = ((const uint8_t*)&(addr->s4.sin_addr));
return (u[0] == 127);
} else if(addr->ss.sa_family == AF_INET6) {
const uint8_t *u = ((const uint8_t*)&(addr->s6.sin6_addr));
if(u[15] == 1) {
int i;
for(i=0;i<15;++i) {
if(u[i])
return 0;
}
return 1;
}
}
}
return 0;
int ioa_addr_is_loopback(ioa_addr *addr) {
if (addr) {
if (addr->ss.sa_family == AF_INET) {
const uint8_t *u = ((const uint8_t *)&(addr->s4.sin_addr));
return (u[0] == 127);
} else if (addr->ss.sa_family == AF_INET6) {
const uint8_t *u = ((const uint8_t *)&(addr->s6.sin6_addr));
if (u[15] == 1) {
int i;
for (i = 0; i < 15; ++i) {
if (u[i])
return 0;
}
return 1;
}
}
}
return 0;
}
/*
To avoid a vulnerability this function checks whether the addr is in 0.0.0.0/8 or ::/128.
Source from (INADDR_ANY) 0.0.0.0/32 and (in6addr_any) ::/128 routed to loopback on Linux systems for old BSD backward compatibility.
https://github.com/torvalds/linux/blob/a2f5ea9e314ba6778f885c805c921e9362ec0420/net/ipv6/tcp_ipv6.c#L182
Source from (INADDR_ANY) 0.0.0.0/32 and (in6addr_any) ::/128 routed to loopback on Linux systems for old BSD backward
compatibility. https://github.com/torvalds/linux/blob/a2f5ea9e314ba6778f885c805c921e9362ec0420/net/ipv6/tcp_ipv6.c#L182
To avoid any trouble we match the whole 0.0.0.0/8 that defined in RFC6890 as local network "this".
*/
int ioa_addr_is_zero(ioa_addr *addr)
{
if(addr) {
if(addr->ss.sa_family == AF_INET) {
const uint8_t *u = ((const uint8_t*)&(addr->s4.sin_addr));
return (u[0] == 0);
} else if(addr->ss.sa_family == AF_INET6) {
const uint8_t *u = ((const uint8_t*)&(addr->s6.sin6_addr));
int i;
for(i=0;i<=15;++i) {
if(u[i])
return 0;
}
return 1;
}
}
return 0;
int ioa_addr_is_zero(ioa_addr *addr) {
if (addr) {
if (addr->ss.sa_family == AF_INET) {
const uint8_t *u = ((const uint8_t *)&(addr->s4.sin_addr));
return (u[0] == 0);
} else if (addr->ss.sa_family == AF_INET6) {
const uint8_t *u = ((const uint8_t *)&(addr->s6.sin6_addr));
int i;
for (i = 0; i <= 15; ++i) {
if (u[i])
return 0;
}
return 1;
}
}
return 0;
}
/////// Map "public" address to "private" address //////////////
@ -533,44 +542,40 @@ static ioa_addr **private_addrs = NULL;
static size_t mcount = 0;
static size_t msz = 0;
void ioa_addr_add_mapping(ioa_addr *apub, ioa_addr *apriv)
{
size_t new_size = msz + sizeof(ioa_addr*);
public_addrs = (ioa_addr**)realloc(public_addrs, new_size);
private_addrs = (ioa_addr**)realloc(private_addrs, new_size);
public_addrs[mcount]=(ioa_addr*)malloc(sizeof(ioa_addr));
private_addrs[mcount]=(ioa_addr*)malloc(sizeof(ioa_addr));
addr_cpy(public_addrs[mcount],apub);
addr_cpy(private_addrs[mcount],apriv);
++mcount;
msz += sizeof(ioa_addr*);
void ioa_addr_add_mapping(ioa_addr *apub, ioa_addr *apriv) {
size_t new_size = msz + sizeof(ioa_addr *);
public_addrs = (ioa_addr **)realloc(public_addrs, new_size);
private_addrs = (ioa_addr **)realloc(private_addrs, new_size);
public_addrs[mcount] = (ioa_addr *)malloc(sizeof(ioa_addr));
private_addrs[mcount] = (ioa_addr *)malloc(sizeof(ioa_addr));
addr_cpy(public_addrs[mcount], apub);
addr_cpy(private_addrs[mcount], apriv);
++mcount;
msz += sizeof(ioa_addr *);
}
void map_addr_from_public_to_private(const ioa_addr *public_addr, ioa_addr *private_addr)
{
size_t i;
for(i=0;i<mcount;++i) {
if(addr_eq_no_port(public_addr,public_addrs[i])) {
addr_cpy(private_addr,private_addrs[i]);
addr_set_port(private_addr,addr_get_port(public_addr));
return;
}
}
addr_cpy(private_addr,public_addr);
void map_addr_from_public_to_private(const ioa_addr *public_addr, ioa_addr *private_addr) {
size_t i;
for (i = 0; i < mcount; ++i) {
if (addr_eq_no_port(public_addr, public_addrs[i])) {
addr_cpy(private_addr, private_addrs[i]);
addr_set_port(private_addr, addr_get_port(public_addr));
return;
}
}
addr_cpy(private_addr, public_addr);
}
void map_addr_from_private_to_public(const ioa_addr *private_addr, ioa_addr *public_addr)
{
size_t i;
for(i=0;i<mcount;++i) {
if(addr_eq_no_port(private_addr,private_addrs[i])) {
addr_cpy(public_addr,public_addrs[i]);
addr_set_port(public_addr,addr_get_port(private_addr));
return;
}
}
addr_cpy(public_addr,private_addr);
void map_addr_from_private_to_public(const ioa_addr *private_addr, ioa_addr *public_addr) {
size_t i;
for (i = 0; i < mcount; ++i) {
if (addr_eq_no_port(private_addr, private_addrs[i])) {
addr_cpy(public_addr, public_addrs[i]);
addr_set_port(public_addr, addr_get_port(private_addr));
return;
}
}
addr_cpy(public_addr, private_addr);
}
//////////////////////////////////////////////////////////////////////////////

View File

@ -54,36 +54,36 @@ typedef struct {
////////////////////////////
uint32_t get_ioa_addr_len(const ioa_addr* addr);
uint32_t get_ioa_addr_len(const ioa_addr *addr);
////////////////////////////
void addr_set_any(ioa_addr *addr);
int addr_any(const ioa_addr* addr);
int addr_any_no_port(const ioa_addr* addr);
int addr_any(const ioa_addr *addr);
int addr_any_no_port(const ioa_addr *addr);
uint32_t addr_hash(const ioa_addr *addr);
uint32_t addr_hash_no_port(const ioa_addr *addr);
void addr_cpy(ioa_addr* dst, const ioa_addr* src);
void addr_cpy4(ioa_addr* dst, const struct sockaddr_in* src);
void addr_cpy6(ioa_addr* dst, const struct sockaddr_in6* src);
int addr_eq(const ioa_addr* a1, const ioa_addr *a2);
int addr_eq_no_port(const ioa_addr* a1, const ioa_addr *a2);
int make_ioa_addr(const uint8_t* saddr, int port, ioa_addr *addr);
int make_ioa_addr_from_full_string(const uint8_t* saddr, int default_port, ioa_addr *addr);
void addr_set_port(ioa_addr* addr, int port);
int addr_get_port(const ioa_addr* addr);
int addr_to_string(const ioa_addr* addr, uint8_t* saddr);
int addr_to_string_no_port(const ioa_addr* addr, uint8_t* saddr);
void addr_cpy(ioa_addr *dst, const ioa_addr *src);
void addr_cpy4(ioa_addr *dst, const struct sockaddr_in *src);
void addr_cpy6(ioa_addr *dst, const struct sockaddr_in6 *src);
int addr_eq(const ioa_addr *a1, const ioa_addr *a2);
int addr_eq_no_port(const ioa_addr *a1, const ioa_addr *a2);
int make_ioa_addr(const uint8_t *saddr, int port, ioa_addr *addr);
int make_ioa_addr_from_full_string(const uint8_t *saddr, int default_port, ioa_addr *addr);
void addr_set_port(ioa_addr *addr, int port);
int addr_get_port(const ioa_addr *addr);
int addr_to_string(const ioa_addr *addr, uint8_t *saddr);
int addr_to_string_no_port(const ioa_addr *addr, uint8_t *saddr);
uint32_t hash_int32(uint32_t a);
uint64_t hash_int64(uint64_t a);
///////////////////////////////////////////
void ioa_addr_range_set(ioa_addr_range* range, const ioa_addr* addr_min, const ioa_addr* addr_max);
int addr_less_eq(const ioa_addr* addr1, const ioa_addr* addr2);
int ioa_addr_in_range(const ioa_addr_range* range, const ioa_addr* addr);
void ioa_addr_range_cpy(ioa_addr_range* dest, const ioa_addr_range* src);
void ioa_addr_range_set(ioa_addr_range *range, const ioa_addr *addr_min, const ioa_addr *addr_max);
int addr_less_eq(const ioa_addr *addr1, const ioa_addr *addr2);
int ioa_addr_in_range(const ioa_addr_range *range, const ioa_addr *addr);
void ioa_addr_range_cpy(ioa_addr_range *dest, const ioa_addr_range *src);
/////// Check whether this is a good address //////////////

File diff suppressed because it is too large Load Diff

View File

@ -45,17 +45,17 @@ extern "C" {
*/
#define STUN_TID_SIZE (12)
typedef struct {
/**
* Binary array
*/
/**
* Binary array
*/
uint8_t tsx_id[STUN_TID_SIZE];
} stun_tid;
typedef enum {
TURN_CREDENTIALS_NONE = 0,
TURN_CREDENTIALS_LONG_TERM,
TURN_CREDENTIALS_SHORT_TERM,
TURN_CREDENTIALS_UNDEFINED
TURN_CREDENTIALS_NONE = 0,
TURN_CREDENTIALS_LONG_TERM,
TURN_CREDENTIALS_SHORT_TERM,
TURN_CREDENTIALS_UNDEFINED
} turn_credential_type;
/**
@ -63,18 +63,18 @@ typedef enum {
*/
typedef uint8_t hmackey_t[64];
typedef uint8_t password_t[STUN_MAX_PWD_SIZE+1];
typedef uint8_t password_t[STUN_MAX_PWD_SIZE + 1];
typedef unsigned long band_limit_t;
///////////////////////////////////
typedef const void* stun_attr_ref;
typedef const void *stun_attr_ref;
//////////////////////////////////////////////////////////////
int stun_tid_equals(const stun_tid *id1, const stun_tid *id2);
void stun_tid_cpy(stun_tid *id_dst, const stun_tid *id_src);
void stun_tid_generate(stun_tid* id);
void stun_tid_generate(stun_tid *id);
///////////////////////////////////////////////////////////////
@ -86,7 +86,8 @@ uint16_t stun_make_error_response(uint16_t method);
///////////////////////////////////////////////////////////////
turn_time_t stun_adjust_allocate_lifetime(turn_time_t lifetime, turn_time_t max_allowed_lifetime, turn_time_t max_lifetime);
turn_time_t stun_adjust_allocate_lifetime(turn_time_t lifetime, turn_time_t max_allowed_lifetime,
turn_time_t max_lifetime);
///////////// STR ////////////////////////////////////////////////
@ -95,79 +96,85 @@ int stun_method_str(uint16_t method, char *smethod);
int stun_get_message_len_str(uint8_t *buf, size_t len, int padding, size_t *app_len);
void stun_init_buffer_str(uint8_t *buf, size_t *len);
void stun_init_command_str(uint16_t message_type, uint8_t* buf, size_t *len);
void old_stun_init_command_str(uint16_t message_type, uint8_t* buf, size_t *len, uint32_t cookie);
void stun_init_request_str(uint16_t method, uint8_t* buf, size_t *len);
void stun_init_indication_str(uint16_t method, uint8_t* buf, size_t *len);
void stun_init_success_response_str(uint16_t method, uint8_t* buf, size_t *len, stun_tid* id);
void old_stun_init_success_response_str(uint16_t method, uint8_t* buf, size_t *len, stun_tid* id, uint32_t cookie);
void stun_init_error_response_str(uint16_t method, uint8_t* buf, size_t *len, uint16_t error_code, const uint8_t *reason, stun_tid* id);
void old_stun_init_error_response_str(uint16_t method, uint8_t* buf, size_t *len, uint16_t error_code, const uint8_t *reason, stun_tid* id, uint32_t cookie);
int stun_init_channel_message_str(uint16_t chnumber, uint8_t* buf, size_t *len, int length, int do_padding);
void stun_init_command_str(uint16_t message_type, uint8_t *buf, size_t *len);
void old_stun_init_command_str(uint16_t message_type, uint8_t *buf, size_t *len, uint32_t cookie);
void stun_init_request_str(uint16_t method, uint8_t *buf, size_t *len);
void stun_init_indication_str(uint16_t method, uint8_t *buf, size_t *len);
void stun_init_success_response_str(uint16_t method, uint8_t *buf, size_t *len, stun_tid *id);
void old_stun_init_success_response_str(uint16_t method, uint8_t *buf, size_t *len, stun_tid *id, uint32_t cookie);
void stun_init_error_response_str(uint16_t method, uint8_t *buf, size_t *len, uint16_t error_code,
const uint8_t *reason, stun_tid *id);
void old_stun_init_error_response_str(uint16_t method, uint8_t *buf, size_t *len, uint16_t error_code,
const uint8_t *reason, stun_tid *id, uint32_t cookie);
int stun_init_channel_message_str(uint16_t chnumber, uint8_t *buf, size_t *len, int length, int do_padding);
int stun_is_command_message_str(const uint8_t* buf, size_t blen);
int old_stun_is_command_message_str(const uint8_t* buf, size_t blen, uint32_t *cookie);
int stun_is_command_message_full_check_str(const uint8_t* buf, size_t blen, int must_check_fingerprint, int *fingerprint_present);
int stun_is_command_message_offset_str(const uint8_t* buf, size_t blen, int offset);
int stun_is_request_str(const uint8_t* buf, size_t len);
int stun_is_success_response_str(const uint8_t* buf, size_t len);
int stun_is_error_response_str(const uint8_t* buf, size_t len, int *err_code, uint8_t *err_msg, size_t err_msg_size);
int stun_is_challenge_response_str(const uint8_t* buf, size_t len, int *err_code, uint8_t *err_msg, size_t err_msg_size, uint8_t *realm, uint8_t *nonce, uint8_t *server_name, int *oauth);
int stun_is_response_str(const uint8_t* buf, size_t len);
int stun_is_indication_str(const uint8_t* buf, size_t len);
int stun_is_command_message_str(const uint8_t *buf, size_t blen);
int old_stun_is_command_message_str(const uint8_t *buf, size_t blen, uint32_t *cookie);
int stun_is_command_message_full_check_str(const uint8_t *buf, size_t blen, int must_check_fingerprint,
int *fingerprint_present);
int stun_is_command_message_offset_str(const uint8_t *buf, size_t blen, int offset);
int stun_is_request_str(const uint8_t *buf, size_t len);
int stun_is_success_response_str(const uint8_t *buf, size_t len);
int stun_is_error_response_str(const uint8_t *buf, size_t len, int *err_code, uint8_t *err_msg, size_t err_msg_size);
int stun_is_challenge_response_str(const uint8_t *buf, size_t len, int *err_code, uint8_t *err_msg, size_t err_msg_size,
uint8_t *realm, uint8_t *nonce, uint8_t *server_name, int *oauth);
int stun_is_response_str(const uint8_t *buf, size_t len);
int stun_is_indication_str(const uint8_t *buf, size_t len);
uint16_t stun_get_method_str(const uint8_t *buf, size_t len);
uint16_t stun_get_msg_type_str(const uint8_t *buf, size_t len);
int stun_is_channel_message_str(const uint8_t *buf, size_t *blen, uint16_t* chnumber, int mandatory_padding);
int is_channel_msg_str(const uint8_t* buf, size_t blen);
int stun_is_channel_message_str(const uint8_t *buf, size_t *blen, uint16_t *chnumber, int mandatory_padding);
int is_channel_msg_str(const uint8_t *buf, size_t blen);
void stun_set_binding_request_str(uint8_t* buf, size_t *len);
int stun_set_binding_response_str(uint8_t* buf, size_t *len, stun_tid* tid,
const ioa_addr *reflexive_addr, int error_code,
const uint8_t *reason,
uint32_t cookie, int old_stun, int no_stun_backward_compatibility);
int stun_is_binding_request_str(const uint8_t* buf, size_t len, size_t offset);
int stun_is_binding_response_str(const uint8_t* buf, size_t len);
void stun_set_binding_request_str(uint8_t *buf, size_t *len);
int stun_set_binding_response_str(uint8_t *buf, size_t *len, stun_tid *tid, const ioa_addr *reflexive_addr,
int error_code, const uint8_t *reason, uint32_t cookie, int old_stun,
int no_stun_backward_compatibility);
int stun_is_binding_request_str(const uint8_t *buf, size_t len, size_t offset);
int stun_is_binding_response_str(const uint8_t *buf, size_t len);
void stun_tid_from_message_str(const uint8_t* buf, size_t len, stun_tid* id);
void stun_tid_message_cpy(uint8_t *buf, const stun_tid* id);
void stun_tid_generate_in_message_str(uint8_t* buf, stun_tid* id);
void stun_tid_from_message_str(const uint8_t *buf, size_t len, stun_tid *id);
void stun_tid_message_cpy(uint8_t *buf, const stun_tid *id);
void stun_tid_generate_in_message_str(uint8_t *buf, stun_tid *id);
int stun_get_command_message_len_str(const uint8_t* buf, size_t len);
int stun_get_command_message_len_str(const uint8_t *buf, size_t len);
const uint8_t* get_default_reason(int error_code);
const uint8_t *get_default_reason(int error_code);
int stun_attr_is_addr(stun_attr_ref attr);
int stun_attr_get_type(stun_attr_ref attr);
int stun_attr_get_len(stun_attr_ref attr);
const uint8_t* stun_attr_get_value(stun_attr_ref attr);
const uint8_t *stun_attr_get_value(stun_attr_ref attr);
uint16_t stun_attr_get_channel_number(stun_attr_ref attr);
band_limit_t stun_attr_get_bandwidth(stun_attr_ref attr);
uint8_t stun_attr_get_even_port(stun_attr_ref attr);
uint64_t stun_attr_get_reservation_token_value(stun_attr_ref attr);
stun_attr_ref stun_attr_get_first_by_type_str(const uint8_t* buf, size_t len, uint16_t attr_type);
stun_attr_ref stun_attr_get_first_str(const uint8_t* buf, size_t len);
stun_attr_ref stun_attr_get_next_str(const uint8_t* buf, size_t len, stun_attr_ref prev);
int stun_attr_add_str(uint8_t* buf, size_t *len, uint16_t attr, const uint8_t* avalue, int alen);
int stun_attr_add_addr_str(uint8_t *buf, size_t *len, uint16_t attr_type, const ioa_addr* ca);
int stun_attr_get_addr_str(const uint8_t *buf, size_t len, stun_attr_ref attr, ioa_addr* ca, const ioa_addr *default_addr);
int stun_attr_get_first_addr_str(const uint8_t *buf, size_t len, uint16_t attr_type, ioa_addr* ca, const ioa_addr *default_addr);
int stun_attr_add_channel_number_str(uint8_t* buf, size_t *len, uint16_t chnumber);
int stun_attr_add_bandwidth_str(uint8_t* buf, size_t *len, band_limit_t bps);
int stun_attr_add_address_error_code(uint8_t* buf, size_t *len, int requested_address_family, int error_code);
stun_attr_ref stun_attr_get_first_by_type_str(const uint8_t *buf, size_t len, uint16_t attr_type);
stun_attr_ref stun_attr_get_first_str(const uint8_t *buf, size_t len);
stun_attr_ref stun_attr_get_next_str(const uint8_t *buf, size_t len, stun_attr_ref prev);
int stun_attr_add_str(uint8_t *buf, size_t *len, uint16_t attr, const uint8_t *avalue, int alen);
int stun_attr_add_addr_str(uint8_t *buf, size_t *len, uint16_t attr_type, const ioa_addr *ca);
int stun_attr_get_addr_str(const uint8_t *buf, size_t len, stun_attr_ref attr, ioa_addr *ca,
const ioa_addr *default_addr);
int stun_attr_get_first_addr_str(const uint8_t *buf, size_t len, uint16_t attr_type, ioa_addr *ca,
const ioa_addr *default_addr);
int stun_attr_add_channel_number_str(uint8_t *buf, size_t *len, uint16_t chnumber);
int stun_attr_add_bandwidth_str(uint8_t *buf, size_t *len, band_limit_t bps);
int stun_attr_add_address_error_code(uint8_t *buf, size_t *len, int requested_address_family, int error_code);
/* return +1 if present, 0 if not, -1 if error: */
int stun_attr_get_address_error_code(uint8_t* buf, size_t len, int *requested_address_family, int *error_code);
int stun_attr_get_address_error_code(uint8_t *buf, size_t len, int *requested_address_family, int *error_code);
uint16_t stun_attr_get_first_channel_number_str(const uint8_t *buf, size_t len);
int stun_set_allocate_request_str(uint8_t* buf, size_t *len, uint32_t lifetime, int af4, int af6, uint8_t transport, int mobile, const char* rt, int ep);
int stun_set_allocate_response_str(uint8_t* buf, size_t *len, stun_tid* tid,
const ioa_addr *relayed_addr1, const ioa_addr *relayed_addr2,
const ioa_addr *reflexive_addr,
uint32_t lifetime, uint32_t max_lifetime, int error_code, const uint8_t *reason,
uint64_t reservation_token, char *mobile_id);
int stun_set_allocate_request_str(uint8_t *buf, size_t *len, uint32_t lifetime, int af4, int af6, uint8_t transport,
int mobile, const char *rt, int ep);
int stun_set_allocate_response_str(uint8_t *buf, size_t *len, stun_tid *tid, const ioa_addr *relayed_addr1,
const ioa_addr *relayed_addr2, const ioa_addr *reflexive_addr, uint32_t lifetime,
uint32_t max_lifetime, int error_code, const uint8_t *reason,
uint64_t reservation_token, char *mobile_id);
uint16_t stun_set_channel_bind_request_str(uint8_t* buf, size_t *len,
const ioa_addr* peer_addr, uint16_t channel_number);
void stun_set_channel_bind_response_str(uint8_t* buf, size_t *len, stun_tid* tid, int error_code, const uint8_t *reason);
uint16_t stun_set_channel_bind_request_str(uint8_t *buf, size_t *len, const ioa_addr *peer_addr,
uint16_t channel_number);
void stun_set_channel_bind_response_str(uint8_t *buf, size_t *len, stun_tid *tid, int error_code,
const uint8_t *reason);
int stun_get_requested_address_family(stun_attr_ref attr);
@ -175,18 +182,24 @@ int stun_attr_add_fingerprint_str(uint8_t *buf, size_t *len);
int SASLprep(uint8_t *s);
#define print_bin(str, len, field) print_bin_func(str,len,field,__FUNCTION__)
#define print_bin(str, len, field) print_bin_func(str, len, field, __FUNCTION__)
void print_bin_func(const char *name, size_t len, const void *s, const char *func);
/*
* Return -1 if failure, 0 if the integrity is not correct, 1 if OK
*/
int stun_check_message_integrity_by_key_str(turn_credential_type ct, uint8_t *buf, size_t len, hmackey_t key, password_t pwd, SHATYPE shatype);
int stun_check_message_integrity_str(turn_credential_type ct, uint8_t *buf, size_t len, const uint8_t *uname, const uint8_t *realm, const uint8_t *upwd, SHATYPE shatype);
int stun_attr_add_integrity_str(turn_credential_type ct, uint8_t *buf, size_t *len, hmackey_t key, password_t pwd, SHATYPE shatype);
int stun_attr_add_integrity_by_key_str(uint8_t *buf, size_t *len, const uint8_t *uname, const uint8_t *realm, hmackey_t key, const uint8_t *nonce, SHATYPE shatype);
int stun_attr_add_integrity_by_user_str(uint8_t *buf, size_t *len, const uint8_t *uname, const uint8_t *realm, const uint8_t *upwd, const uint8_t *nonce, SHATYPE shatype);
int stun_attr_add_integrity_by_user_short_term_str(uint8_t *buf, size_t *len, const uint8_t *uname, password_t pwd, SHATYPE shatype);
int stun_check_message_integrity_by_key_str(turn_credential_type ct, uint8_t *buf, size_t len, hmackey_t key,
password_t pwd, SHATYPE shatype);
int stun_check_message_integrity_str(turn_credential_type ct, uint8_t *buf, size_t len, const uint8_t *uname,
const uint8_t *realm, const uint8_t *upwd, SHATYPE shatype);
int stun_attr_add_integrity_str(turn_credential_type ct, uint8_t *buf, size_t *len, hmackey_t key, password_t pwd,
SHATYPE shatype);
int stun_attr_add_integrity_by_key_str(uint8_t *buf, size_t *len, const uint8_t *uname, const uint8_t *realm,
hmackey_t key, const uint8_t *nonce, SHATYPE shatype);
int stun_attr_add_integrity_by_user_str(uint8_t *buf, size_t *len, const uint8_t *uname, const uint8_t *realm,
const uint8_t *upwd, const uint8_t *nonce, SHATYPE shatype);
int stun_attr_add_integrity_by_user_short_term_str(uint8_t *buf, size_t *len, const uint8_t *uname, password_t pwd,
SHATYPE shatype);
size_t get_hmackey_size(SHATYPE shatype);
/*
@ -196,8 +209,10 @@ size_t get_hmackey_size(SHATYPE shatype);
#define TURN_RANDOM_SIZE (sizeof(long))
long turn_random(void);
int stun_produce_integrity_key_str(const uint8_t *uname, const uint8_t *realm, const uint8_t *upwd, hmackey_t key, SHATYPE shatype);
int stun_calculate_hmac(const uint8_t *buf, size_t len, const uint8_t *key, size_t sz, uint8_t *hmac, unsigned int *hmac_len, SHATYPE shatype);
int stun_produce_integrity_key_str(const uint8_t *uname, const uint8_t *realm, const uint8_t *upwd, hmackey_t key,
SHATYPE shatype);
int stun_calculate_hmac(const uint8_t *buf, size_t len, const uint8_t *key, size_t sz, uint8_t *hmac,
unsigned int *hmac_len, SHATYPE shatype);
/* RFC 5780 */
int stun_attr_get_change_request_str(stun_attr_ref attr, int *change_ip, int *change_port);
@ -212,12 +227,14 @@ int is_http(const char *s, size_t blen);
/* OAUTH */
int convert_oauth_key_data(const oauth_key_data *oakd, oauth_key *key, char *err_msg, size_t err_msg_size);
int decode_oauth_token(const uint8_t *server_name, const encoded_oauth_token *etoken, const oauth_key *key, oauth_token *dtoken);
int encode_oauth_token(const uint8_t *server_name, encoded_oauth_token *etoken, const oauth_key *key, const oauth_token *dtoken, const uint8_t *nonce);
int decode_oauth_token(const uint8_t *server_name, const encoded_oauth_token *etoken, const oauth_key *key,
oauth_token *dtoken);
int encode_oauth_token(const uint8_t *server_name, encoded_oauth_token *etoken, const oauth_key *key,
const oauth_token *dtoken, const uint8_t *nonce);
/* Encrypted password */
void generate_new_enc_password(const char* pwd, char *result);
int check_password(const char* pin, const char* pwd);
void generate_new_enc_password(const char *pwd, char *result);
int check_password(const char *pin, const char *pwd);
///////////////////////////////////////////////////////////////

View File

@ -32,71 +32,72 @@
//////////////////////////////////////////////////////////////////////////////
int stun_addr_encode(const ioa_addr* ca, uint8_t *cfield, int *clen, int xor_ed, uint32_t mc, const uint8_t *tsx_id) {
int stun_addr_encode(const ioa_addr *ca, uint8_t *cfield, int *clen, int xor_ed, uint32_t mc, const uint8_t *tsx_id) {
if(!cfield || !clen || !ca || !tsx_id) return -1;
if (!cfield || !clen || !ca || !tsx_id)
return -1;
if (ca->ss.sa_family == AF_INET || ca->ss.sa_family==0) {
if (ca->ss.sa_family == AF_INET || ca->ss.sa_family == 0) {
/* IPv4 address */
*clen=8;
cfield[0]=0;
cfield[1]=1; //IPv4 family
*clen = 8;
cfield[0] = 0;
cfield[1] = 1; // IPv4 family
if (xor_ed) {
/* Port */
((uint16_t*)cfield)[1] = (ca->s4.sin_port) ^ nswap16(mc >> 16);
((uint16_t *)cfield)[1] = (ca->s4.sin_port) ^ nswap16(mc >> 16);
/* Address */
((uint32_t*)cfield)[1] = (ca->s4.sin_addr.s_addr) ^ nswap32(mc);
((uint32_t *)cfield)[1] = (ca->s4.sin_addr.s_addr) ^ nswap32(mc);
} else {
/* Port */
((uint16_t*)cfield)[1]=ca->s4.sin_port;
((uint16_t *)cfield)[1] = ca->s4.sin_port;
/* Address */
((uint32_t*)cfield)[1]=ca->s4.sin_addr.s_addr;
((uint32_t *)cfield)[1] = ca->s4.sin_addr.s_addr;
}
} else if (ca->ss.sa_family == AF_INET6) {
/* IPv6 address */
*clen=20;
*clen = 20;
cfield[0] = 0;
cfield[1] = 2; // IPv6 family
cfield[0]=0;
cfield[1]=2; //IPv6 family
if (xor_ed) {
unsigned int i;
uint8_t *dst = ((uint8_t*)cfield)+4;
const uint8_t *src = (const uint8_t*)&(ca->s6.sin6_addr);
uint8_t *dst = ((uint8_t *)cfield) + 4;
const uint8_t *src = (const uint8_t *)&(ca->s6.sin6_addr);
uint32_t magic = nswap32(mc);
/* Port */
((uint16_t*)cfield)[1] = ca->s6.sin6_port ^ nswap16(mc >> 16);
((uint16_t *)cfield)[1] = ca->s6.sin6_port ^ nswap16(mc >> 16);
/* Address */
for (i=0; i<4; ++i) {
dst[i] = (uint8_t)(src[i] ^ ((const uint8_t*)&magic)[i]);
for (i = 0; i < 4; ++i) {
dst[i] = (uint8_t)(src[i] ^ ((const uint8_t *)&magic)[i]);
}
for (i=0; i<12; ++i) {
dst[i+4] = (uint8_t)(src[i+4] ^ tsx_id[i]);
for (i = 0; i < 12; ++i) {
dst[i + 4] = (uint8_t)(src[i + 4] ^ tsx_id[i]);
}
} else {
/* Port */
((uint16_t*)cfield)[1]=ca->s6.sin6_port;
((uint16_t *)cfield)[1] = ca->s6.sin6_port;
/* Address */
memcpy(((uint8_t*)cfield)+4, &ca->s6.sin6_addr, 16);
memcpy(((uint8_t *)cfield) + 4, &ca->s6.sin6_addr, 16);
}
} else {
@ -106,34 +107,39 @@ int stun_addr_encode(const ioa_addr* ca, uint8_t *cfield, int *clen, int xor_ed,
return 0;
}
int stun_addr_decode(ioa_addr* ca, const uint8_t *cfield, int len, int xor_ed, uint32_t mc, const uint8_t *tsx_id) {
int stun_addr_decode(ioa_addr *ca, const uint8_t *cfield, int len, int xor_ed, uint32_t mc, const uint8_t *tsx_id) {
if(!cfield || !len || !ca || !tsx_id || (len<8)) return -1;
if (!cfield || !len || !ca || !tsx_id || (len < 8))
return -1;
if(cfield[0]!=0) {
if (cfield[0] != 0) {
return -1;
}
int sa_family;
if(cfield[1]==1) sa_family=AF_INET;
else if(cfield[1]==2) sa_family=AF_INET6;
else return -1;
ca->ss.sa_family=sa_family;
if (cfield[1] == 1)
sa_family = AF_INET;
else if (cfield[1] == 2)
sa_family = AF_INET6;
else
return -1;
ca->ss.sa_family = sa_family;
if (sa_family == AF_INET) {
if(len!=8) return -1;
if (len != 8)
return -1;
/* IPv4 address */
/* Port */
ca->s4.sin_port=((const uint16_t*)cfield)[1];
ca->s4.sin_port = ((const uint16_t *)cfield)[1];
/* Address */
ca->s4.sin_addr.s_addr=((const uint32_t*)cfield)[1];
ca->s4.sin_addr.s_addr = ((const uint32_t *)cfield)[1];
if (xor_ed) {
ca->s4.sin_port ^= nswap16(mc >> 16);
ca->s4.sin_addr.s_addr ^= nswap32(mc);
@ -143,13 +149,14 @@ int stun_addr_decode(ioa_addr* ca, const uint8_t *cfield, int len, int xor_ed, u
/* IPv6 address */
if(len!=20) return -1;
if (len != 20)
return -1;
/* Port */
ca->s6.sin6_port = ((const uint16_t*)cfield)[1];
ca->s6.sin6_port = ((const uint16_t *)cfield)[1];
/* Address */
memcpy(&ca->s6.sin6_addr, ((const uint8_t*)cfield)+4, 16);
memcpy(&ca->s6.sin6_addr, ((const uint8_t *)cfield) + 4, 16);
if (xor_ed) {
@ -162,13 +169,13 @@ int stun_addr_decode(ioa_addr* ca, const uint8_t *cfield, int len, int xor_ed, u
ca->s6.sin6_port ^= nswap16(mc >> 16);
/* Address */
src = ((const uint8_t*)cfield)+4;
dst = (uint8_t*)&ca->s6.sin6_addr;
for (i=0; i<4; ++i) {
dst[i] = (uint8_t)(src[i] ^ ((const uint8_t*)&magic)[i]);
src = ((const uint8_t *)cfield) + 4;
dst = (uint8_t *)&ca->s6.sin6_addr;
for (i = 0; i < 4; ++i) {
dst[i] = (uint8_t)(src[i] ^ ((const uint8_t *)&magic)[i]);
}
for (i=0; i<12; ++i) {
dst[i+4] = (uint8_t)(src[i+4] ^ tsx_id[i]);
for (i = 0; i < 12; ++i) {
dst[i + 4] = (uint8_t)(src[i + 4] ^ tsx_id[i]);
}
}
@ -180,4 +187,3 @@ int stun_addr_decode(ioa_addr* ca, const uint8_t *cfield, int len, int xor_ed, u
}
//////////////////////////////////////////////////////////////////////////////

View File

@ -39,8 +39,8 @@ extern "C" {
///////////////////////////////////////////
int stun_addr_encode(const ioa_addr* ca, uint8_t *cfield, int *clen, int xor_ed, uint32_t mc, const uint8_t *tsx_id);
int stun_addr_decode(ioa_addr* ca, const uint8_t *cfield, int len, int xor_ed, uint32_t mc, const uint8_t *tsx_id);
int stun_addr_encode(const ioa_addr *ca, uint8_t *cfield, int *clen, int xor_ed, uint32_t mc, const uint8_t *tsx_id);
int stun_addr_decode(ioa_addr *ca, const uint8_t *cfield, int len, int xor_ed, uint32_t mc, const uint8_t *tsx_id);
///////////////////////////////////////////

View File

@ -49,15 +49,15 @@
#define STUN_MAGIC_COOKIE (0x2112A442)
#define IS_STUN_REQUEST(msg_type) (((msg_type) & 0x0110) == 0x0000)
#define IS_STUN_INDICATION(msg_type) (((msg_type) & 0x0110) == 0x0010)
#define IS_STUN_SUCCESS_RESP(msg_type) (((msg_type) & 0x0110) == 0x0100)
#define IS_STUN_ERR_RESP(msg_type) (((msg_type) & 0x0110) == 0x0110)
#define IS_STUN_REQUEST(msg_type) (((msg_type)&0x0110) == 0x0000)
#define IS_STUN_INDICATION(msg_type) (((msg_type)&0x0110) == 0x0010)
#define IS_STUN_SUCCESS_RESP(msg_type) (((msg_type)&0x0110) == 0x0100)
#define IS_STUN_ERR_RESP(msg_type) (((msg_type)&0x0110) == 0x0110)
#define GET_STUN_REQUEST(msg_type) (msg_type & 0xFEEF)
#define GET_STUN_INDICATION(msg_type) ((msg_type & 0xFEEF)|0x0010)
#define GET_STUN_SUCCESS_RESP(msg_type) ((msg_type & 0xFEEF)|0x0100)
#define GET_STUN_ERR_RESP(msg_type) (msg_type | 0x0110)
#define GET_STUN_REQUEST(msg_type) (msg_type & 0xFEEF)
#define GET_STUN_INDICATION(msg_type) ((msg_type & 0xFEEF) | 0x0010)
#define GET_STUN_SUCCESS_RESP(msg_type) ((msg_type & 0xFEEF) | 0x0100)
#define GET_STUN_ERR_RESP(msg_type) (msg_type | 0x0110)
/* Lifetimes: */
#define STUN_DEFAULT_ALLOCATE_LIFETIME (600)
@ -130,7 +130,7 @@
#define STUN_ATTRIBUTE_CONNECTION_ID (0x002A)
/* <<== RFC 6062 */
#define STUN_VALID_CHANNEL(chn) ((chn)>=0x4000 && (chn)<=0x7FFF)
#define STUN_VALID_CHANNEL(chn) ((chn) >= 0x4000 && (chn) <= 0x7FFF)
///////// extra values //////////////////
@ -158,30 +158,32 @@
#define MAXSHASIZE (128)
enum _SHATYPE {
SHATYPE_ERROR = -1,
SHATYPE_DEFAULT=0,
SHATYPE_SHA1=SHATYPE_DEFAULT,
SHATYPE_SHA256,
SHATYPE_SHA384,
SHATYPE_SHA512
SHATYPE_ERROR = -1,
SHATYPE_DEFAULT = 0,
SHATYPE_SHA1 = SHATYPE_DEFAULT,
SHATYPE_SHA256,
SHATYPE_SHA384,
SHATYPE_SHA512
};
typedef enum _SHATYPE SHATYPE;
#define shatype_name(sht) ((sht == SHATYPE_SHA1) ? "SHA1" : ((sht == SHATYPE_SHA256) ? "SHA256" : ((sht == SHATYPE_SHA384) ? "SHA384" : "SHA512")))
#define shatype_name(sht) \
((sht == SHATYPE_SHA1) ? "SHA1" \
: ((sht == SHATYPE_SHA256) ? "SHA256" : ((sht == SHATYPE_SHA384) ? "SHA384" : "SHA512")))
/* <<== SHA */
/* OAUTH TOKEN ENC ALG ==> */
enum _ENC_ALG {
ENC_ALG_ERROR=-1,
ENC_ALG_ERROR = -1,
#if !defined(TURN_NO_GCM)
ENC_ALG_DEFAULT=0,
A256GCM=ENC_ALG_DEFAULT,
A128GCM,
ENC_ALG_DEFAULT = 0,
A256GCM = ENC_ALG_DEFAULT,
A128GCM,
#endif
ENC_ALG_NUM
ENC_ALG_NUM
};
typedef enum _ENC_ALG ENC_ALG;
@ -210,44 +212,44 @@ typedef enum _ENC_ALG ENC_ALG;
#define OAUTH_TIME_DELTA (5)
struct _oauth_key_data {
char kid[OAUTH_KID_SIZE+1];
char ikm_key[OAUTH_KEY_SIZE+1];
size_t ikm_key_size;
turn_time_t timestamp;
turn_time_t lifetime;
char as_rs_alg[OAUTH_ALG_SIZE+1];
char kid[OAUTH_KID_SIZE + 1];
char ikm_key[OAUTH_KEY_SIZE + 1];
size_t ikm_key_size;
turn_time_t timestamp;
turn_time_t lifetime;
char as_rs_alg[OAUTH_ALG_SIZE + 1];
};
typedef struct _oauth_key_data oauth_key_data;
struct _oauth_key {
char kid[OAUTH_KID_SIZE+1];
char ikm_key[OAUTH_KEY_SIZE+1];
size_t ikm_key_size;
turn_time_t timestamp;
turn_time_t lifetime;
ENC_ALG as_rs_alg;
char as_rs_key[OAUTH_KEY_SIZE+1];
size_t as_rs_key_size;
char auth_key[OAUTH_KEY_SIZE+1];
size_t auth_key_size;
char kid[OAUTH_KID_SIZE + 1];
char ikm_key[OAUTH_KEY_SIZE + 1];
size_t ikm_key_size;
turn_time_t timestamp;
turn_time_t lifetime;
ENC_ALG as_rs_alg;
char as_rs_key[OAUTH_KEY_SIZE + 1];
size_t as_rs_key_size;
char auth_key[OAUTH_KEY_SIZE + 1];
size_t auth_key_size;
};
typedef struct _oauth_key oauth_key;
struct _oauth_encrypted_block {
uint16_t nonce_length;
uint8_t nonce[OAUTH_MAX_NONCE_SIZE];
uint16_t key_length;
uint8_t mac_key[MAXSHASIZE];
uint64_t timestamp;
uint32_t lifetime;
uint16_t nonce_length;
uint8_t nonce[OAUTH_MAX_NONCE_SIZE];
uint16_t key_length;
uint8_t mac_key[MAXSHASIZE];
uint64_t timestamp;
uint32_t lifetime;
};
typedef struct _oauth_encrypted_block oauth_encrypted_block;
struct _oauth_token {
oauth_encrypted_block enc_block;
oauth_encrypted_block enc_block;
};
typedef struct _oauth_token oauth_token;
@ -255,8 +257,8 @@ typedef struct _oauth_token oauth_token;
#define MAX_ENCODED_OAUTH_TOKEN_SIZE (1024)
struct _encoded_oauth_token {
char token[MAX_ENCODED_OAUTH_TOKEN_SIZE];
size_t size;
char token[MAX_ENCODED_OAUTH_TOKEN_SIZE];
size_t size;
};
typedef struct _encoded_oauth_token encoded_oauth_token;

View File

@ -44,29 +44,29 @@
#endif
#if defined(WINDOWS)
#include <ws2tcpip.h>
#include <windows.h>
#include <process.h>
#include <windows.h>
#include <ws2tcpip.h>
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <strings.h>
#include <sys/socket.h>
#include <unistd.h>
#endif
#include <sys/types.h>
#include <ctype.h>
#include <errno.h>
#include <inttypes.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <sys/types.h>
#include <time.h>
#include <stdarg.h>
#include <errno.h>
#ifdef __cplusplus
extern "C" {
@ -76,22 +76,21 @@ extern "C" {
#define nswap32(ul) ntohl(ul)
#define nswap64(ull) ioa_ntoh64(ull)
static inline uint64_t _ioa_ntoh64(uint64_t v)
{
static inline uint64_t _ioa_ntoh64(uint64_t v) {
#if BYTE_ORDER == LITTLE_ENDIAN
uint8_t *src = (uint8_t*) &v;
uint8_t* dst = src + 7;
while (src < dst) {
uint8_t vdst = *dst;
*(dst--) = *src;
*(src++) = vdst;
}
uint8_t *src = (uint8_t *)&v;
uint8_t *dst = src + 7;
while (src < dst) {
uint8_t vdst = *dst;
*(dst--) = *src;
*(src++) = vdst;
}
#elif BYTE_ORDER == BIG_ENDIAN
/* OK */
/* OK */
#else
#error WRONG BYTE_ORDER SETTING
#endif
return v;
return v;
}
/* TTL */
@ -105,24 +104,35 @@ static inline uint64_t _ioa_ntoh64(uint64_t v)
#define ioa_ntoh64 _ioa_ntoh64
#define ioa_hton64 _ioa_ntoh64
#define BUFFEREVENT_FREE(be) do { if(be) { bufferevent_flush(be,EV_READ|EV_WRITE,BEV_FLUSH); bufferevent_disable(be,EV_READ|EV_WRITE); bufferevent_free(be); be = NULL;} } while(0)
#define BUFFEREVENT_FREE(be) \
do { \
if (be) { \
bufferevent_flush(be, EV_READ | EV_WRITE, BEV_FLUSH); \
bufferevent_disable(be, EV_READ | EV_WRITE); \
bufferevent_free(be); \
be = NULL; \
} \
} while (0)
#define turn_time() ((turn_time_t)time(NULL))
typedef int vint;
typedef vint* vintp;
typedef vint *vintp;
typedef uint32_t turn_time_t;
#define turn_time_before(t1,t2) ((((int32_t)(t1))-((int32_t)(t2))) < 0)
#define turn_time_before(t1, t2) ((((int32_t)(t1)) - ((int32_t)(t2))) < 0)
#if !defined(UNUSED_ARG)
#define UNUSED_ARG(A) do { A=A; } while(0)
#define UNUSED_ARG(A) \
do { \
A = A; \
} while (0)
#endif
#define MAX_STUN_MESSAGE_SIZE (65507)
#define STUN_BUFFER_SIZE (MAX_STUN_MESSAGE_SIZE)
#define UDP_STUN_BUFFER_SIZE (1024<<4)
#define UDP_STUN_BUFFER_SIZE (1024 << 4)
#define NONCE_LENGTH_32BITS (4)
@ -137,16 +147,18 @@ typedef uint32_t turn_time_t;
#error WRONG BYTE_ORDER SETTING
#endif
#define STRCPY(dst,src) \
do { if((const char*)(dst) != (const char*)(src)) { \
if(sizeof(dst)==sizeof(char*))\
strcpy(((char*)(dst)),(const char*)(src));\
else {\
size_t szdst = sizeof((dst));\
strncpy((char*)(dst),(const char*)(src),szdst);\
((char*)(dst))[szdst-1] = 0;\
}\
} } while(0)
#define STRCPY(dst, src) \
do { \
if ((const char *)(dst) != (const char *)(src)) { \
if (sizeof(dst) == sizeof(char *)) \
strcpy(((char *)(dst)), (const char *)(src)); \
else { \
size_t szdst = sizeof((dst)); \
strncpy((char *)(dst), (const char *)(src), szdst); \
((char *)(dst))[szdst - 1] = 0; \
} \
} \
} while (0)
//////////////// Bufferevents /////////////////////
@ -155,11 +167,13 @@ typedef uint32_t turn_time_t;
//////////////// KERNEL-LEVEL CHANNEL HANDLERS /////////
#if !defined(TURN_CHANNEL_HANDLER_KERNEL)
#define TURN_CHANNEL_HANDLER_KERNEL void*
#define TURN_CHANNEL_HANDLER_KERNEL void *
#endif
#if !defined(CREATE_TURN_CHANNEL_KERNEL)
#define CREATE_TURN_CHANNEL_KERNEL(channel_number, address_family_client, address_family_peer, protocol_client, client_addr, local_addr, local_relay_addr, peer_addr) ((TURN_CHANNEL_HANDLER_KERNEL)(1))
#define CREATE_TURN_CHANNEL_KERNEL(channel_number, address_family_client, address_family_peer, protocol_client, \
client_addr, local_addr, local_relay_addr, peer_addr) \
((TURN_CHANNEL_HANDLER_KERNEL)(1))
#endif
#if !defined(DELETE_TURN_CHANNEL_KERNEL)
@ -200,5 +214,5 @@ typedef uint32_t turn_time_t;
}
#endif
#endif
#endif
/* __IODEFS__ */

File diff suppressed because it is too large Load Diff

View File

@ -31,10 +31,10 @@
#ifndef __TURN_TURN_A_LIB__
#define __TURN_TURN_A_LIB__
#include "ns_turn_utils.h"
#include "ns_turn_msg.h"
#include "ns_turn_ioalib.h"
#include "ns_turn_maps.h"
#include "ns_turn_msg.h"
#include "ns_turn_utils.h"
#ifdef __cplusplus
extern "C" {
@ -47,17 +47,15 @@ extern "C" {
////////////// Network session ////////////////
typedef struct
{
ioa_socket_handle s;
turn_time_t expiration_time;
ioa_timer_handle lifetime_ev;
typedef struct {
ioa_socket_handle s;
turn_time_t expiration_time;
ioa_timer_handle lifetime_ev;
} relay_endpoint_session;
static inline void clear_relay_endpoint_session_data(relay_endpoint_session* cdi)
{
if (cdi)
IOA_CLOSE_SOCKET(cdi->s);
static inline void clear_relay_endpoint_session_data(relay_endpoint_session *cdi) {
if (cdi)
IOA_CLOSE_SOCKET(cdi->s);
}
////////// RFC 6062 TCP connection ////////
@ -65,12 +63,12 @@ static inline void clear_relay_endpoint_session_data(relay_endpoint_session* cdi
#define MAX_UNSENT_BUFFER_SIZE (0x10)
enum _TC_STATE {
TC_STATE_UNKNOWN=0,
TC_STATE_CLIENT_TO_PEER_CONNECTING,
TC_STATE_PEER_CONNECTING,
TC_STATE_PEER_CONNECTED,
TC_STATE_READY,
TC_STATE_FAILED
TC_STATE_UNKNOWN = 0,
TC_STATE_CLIENT_TO_PEER_CONNECTING,
TC_STATE_PEER_CONNECTING,
TC_STATE_PEER_CONNECTED,
TC_STATE_READY,
TC_STATE_FAILED
};
typedef enum _TC_STATE TC_STATE;
@ -78,28 +76,27 @@ typedef enum _TC_STATE TC_STATE;
typedef uint32_t tcp_connection_id;
typedef struct {
size_t sz;
ioa_network_buffer_handle *bufs;
size_t sz;
ioa_network_buffer_handle *bufs;
} unsent_buffer;
struct _tcp_connection
{
TC_STATE state;
tcp_connection_id id;
ioa_addr peer_addr;
ioa_socket_handle client_s;
ioa_socket_handle peer_s;
ioa_timer_handle peer_conn_timeout;
ioa_timer_handle conn_bind_timeout;
stun_tid tid;
void *owner; //a
int done;
unsent_buffer ub_to_client;
struct _tcp_connection {
TC_STATE state;
tcp_connection_id id;
ioa_addr peer_addr;
ioa_socket_handle client_s;
ioa_socket_handle peer_s;
ioa_timer_handle peer_conn_timeout;
ioa_timer_handle conn_bind_timeout;
stun_tid tid;
void *owner; // a
int done;
unsent_buffer ub_to_client;
};
typedef struct _tcp_connection_list {
size_t sz;
tcp_connection **elems;
size_t sz;
tcp_connection **elems;
} tcp_connection_list;
////////////////////////////////
@ -116,7 +113,7 @@ typedef struct _ch_info {
ioa_addr peer_addr;
turn_time_t expiration_time;
ioa_timer_handle lifetime_ev;
void *owner; //perm
void *owner; // perm
TURN_CHANNEL_HANDLER_KERNEL kernel_channel;
} ch_info;
@ -126,43 +123,43 @@ typedef struct _ch_info {
#define CH_MAP_ARRAY_SIZE (0x3)
typedef struct _chn_map_array {
ch_info main_chns[CH_MAP_ARRAY_SIZE];
size_t extra_sz;
ch_info **extra_chns;
ch_info main_chns[CH_MAP_ARRAY_SIZE];
size_t extra_sz;
ch_info **extra_chns;
} ch_map_array;
typedef struct _ch_map {
ch_map_array table[CH_MAP_HASH_SIZE];
ch_map_array table[CH_MAP_HASH_SIZE];
} ch_map;
ch_info *ch_map_get(ch_map* map, uint16_t chnum, int new_chn);
void ch_map_clean(ch_map* map);
ch_info *ch_map_get(ch_map *map, uint16_t chnum, int new_chn);
void ch_map_clean(ch_map *map);
////////////////////////////
typedef struct _turn_permission_info {
int allocated;
lm_map chns;
ioa_addr addr;
turn_time_t expiration_time;
ioa_timer_handle lifetime_ev;
void* owner; //a
int verbose;
unsigned long long session_id;
int allocated;
lm_map chns;
ioa_addr addr;
turn_time_t expiration_time;
ioa_timer_handle lifetime_ev;
void *owner; // a
int verbose;
unsigned long long session_id;
} turn_permission_info;
typedef struct _turn_permission_slot {
turn_permission_info info;
turn_permission_info info;
} turn_permission_slot;
typedef struct _turn_permission_array {
turn_permission_slot main_slots[TURN_PERMISSION_ARRAY_SIZE];
size_t extra_sz;
turn_permission_slot **extra_slots;
turn_permission_slot main_slots[TURN_PERMISSION_ARRAY_SIZE];
size_t extra_sz;
turn_permission_slot **extra_slots;
} turn_permission_array;
typedef struct _turn_permission_hashtable {
turn_permission_array table[TURN_PERMISSION_HASHTABLE_SIZE];
turn_permission_array table[TURN_PERMISSION_HASHTABLE_SIZE];
} turn_permission_hashtable;
//////////////// ALLOCATION //////////////////////
@ -170,7 +167,7 @@ typedef struct _turn_permission_hashtable {
#define ALLOC_IPV4_INDEX (0)
#define ALLOC_IPV6_INDEX (1)
#define ALLOC_PROTOCOLS_NUMBER (2)
#define ALLOC_INDEX(family) ((((family)==AF_INET6)) ? ALLOC_IPV6_INDEX : ALLOC_IPV4_INDEX )
#define ALLOC_INDEX(family) ((((family) == AF_INET6)) ? ALLOC_IPV6_INDEX : ALLOC_IPV4_INDEX)
#define ALLOC_INDEX_ADDR(addr) ALLOC_INDEX(((addr)->ss).sa_family)
typedef struct _allocation {
@ -179,36 +176,36 @@ typedef struct _allocation {
turn_permission_hashtable addr_to_perm;
relay_endpoint_session relay_sessions[ALLOC_PROTOCOLS_NUMBER];
int relay_sessions_failure[ALLOC_PROTOCOLS_NUMBER];
ch_map chns; /* chnum-to-ch_info* */
void *owner; //ss
ur_map *tcp_connections; //global (per turn server) reference
tcp_connection_list tcs; //local reference
ch_map chns; /* chnum-to-ch_info* */
void *owner; // ss
ur_map *tcp_connections; // global (per turn server) reference
tcp_connection_list tcs; // local reference
} allocation;
//////////// CHANNELS ////////////////////
uint16_t get_turn_channel_number(turn_permission_info* tinfo, ioa_addr *addr);
ch_info *get_turn_channel(turn_permission_info* tinfo, ioa_addr *addr);
uint16_t get_turn_channel_number(turn_permission_info *tinfo, ioa_addr *addr);
ch_info *get_turn_channel(turn_permission_info *tinfo, ioa_addr *addr);
void turn_channel_delete(ch_info* chn);
void turn_channel_delete(ch_info *chn);
/////////// ALLOCATION ////////////
void init_allocation(void *owner, allocation* a, ur_map *tcp_connections);
void init_allocation(void *owner, allocation *a, ur_map *tcp_connections);
void clear_allocation(allocation *a, SOCKET_TYPE socket_type);
void turn_permission_clean(turn_permission_info* tinfo);
void turn_permission_clean(turn_permission_info *tinfo);
void set_allocation_lifetime_ev(allocation *a, turn_time_t exp_time, ioa_timer_handle ev, int family);
int is_allocation_valid(const allocation* a);
void set_allocation_valid(allocation* a, int value);
turn_permission_info* allocation_get_permission(allocation* a, const ioa_addr *addr);
turn_permission_hashtable* allocation_get_turn_permission_hashtable(allocation *a);
turn_permission_info* allocation_add_permission(allocation *a, const ioa_addr* addr);
int is_allocation_valid(const allocation *a);
void set_allocation_valid(allocation *a, int value);
turn_permission_info *allocation_get_permission(allocation *a, const ioa_addr *addr);
turn_permission_hashtable *allocation_get_turn_permission_hashtable(allocation *a);
turn_permission_info *allocation_add_permission(allocation *a, const ioa_addr *addr);
ch_info* allocation_get_new_ch_info(allocation* a, uint16_t chnum, ioa_addr* peer_addr);
ch_info* allocation_get_ch_info(allocation* a, uint16_t chnum);
ch_info* allocation_get_ch_info_by_peer_addr(allocation* a, ioa_addr* peer_addr);
ch_info *allocation_get_new_ch_info(allocation *a, uint16_t chnum, ioa_addr *peer_addr);
ch_info *allocation_get_ch_info(allocation *a, uint16_t chnum);
ch_info *allocation_get_ch_info_by_peer_addr(allocation *a, ioa_addr *peer_addr);
relay_endpoint_session *get_relay_session(allocation *a, int family);
int get_relay_session_failure(allocation *a, int family);
@ -220,7 +217,8 @@ tcp_connection *get_and_clean_tcp_connection_by_id(ur_map *map, tcp_connection_i
tcp_connection *get_tcp_connection_by_id(ur_map *map, tcp_connection_id id);
tcp_connection *get_tcp_connection_by_peer(allocation *a, ioa_addr *peer_addr);
int can_accept_tcp_connection_from_peer(allocation *a, ioa_addr *peer_addr, int server_relay);
tcp_connection *create_tcp_connection(uint8_t server_id, allocation *a, stun_tid *tid, ioa_addr *peer_addr, int *err_code);
tcp_connection *create_tcp_connection(uint8_t server_id, allocation *a, stun_tid *tid, ioa_addr *peer_addr,
int *err_code);
void delete_tcp_connection(tcp_connection *tc);
void clear_unsent_buffer(unsent_buffer *ub);

View File

@ -50,41 +50,41 @@ struct _tcp_connection;
typedef struct _tcp_connection tcp_connection;
#if defined(_MSC_VER)
#ifndef strtok_r
#define strtok_r strtok_s
#endif
#ifndef strtok_r
#define strtok_r strtok_s
#endif
#ifndef sleep
#define sleep(t) Sleep(t * 1000)
#endif
#ifndef sleep
#define sleep(t) Sleep(t * 1000)
#endif
#ifndef usleep
#define usleep Sleep
#endif
#ifndef usleep
#define usleep Sleep
#endif
#if !defined(ssize_t) && !defined(_SSIZE_T_)
#include <BaseTsd.h>
typedef SSIZE_T ssize_t;
#endif
#if !defined(ssize_t) && !defined(_SSIZE_T_)
#include <BaseTsd.h>
typedef SSIZE_T ssize_t;
#endif
#endif
////////////// Mutexes /////////////////////
struct _turn_mutex {
uint32_t data;
void* mutex;
void *mutex;
};
typedef struct _turn_mutex turn_mutex;
int turn_mutex_init(turn_mutex* mutex);
int turn_mutex_init_recursive(turn_mutex* mutex);
int turn_mutex_init(turn_mutex *mutex);
int turn_mutex_init_recursive(turn_mutex *mutex);
int turn_mutex_lock(const turn_mutex *mutex);
int turn_mutex_unlock(const turn_mutex *mutex);
int turn_mutex_destroy(turn_mutex* mutex);
int turn_mutex_destroy(turn_mutex *mutex);
#define TURN_MUTEX_DECLARE(mutex) turn_mutex mutex;
#define TURN_MUTEX_INIT(mutex) turn_mutex_init(mutex)
@ -95,37 +95,37 @@ int turn_mutex_destroy(turn_mutex* mutex);
/////// Sockets //////////////////////////////
#define IOA_EV_TIMEOUT 0x01
#define IOA_EV_READ 0x02
#define IOA_EV_WRITE 0x04
#define IOA_EV_SIGNAL 0x08
#define IOA_EV_CLOSE 0x10
#define IOA_EV_TIMEOUT 0x01
#define IOA_EV_READ 0x02
#define IOA_EV_WRITE 0x04
#define IOA_EV_SIGNAL 0x08
#define IOA_EV_CLOSE 0x10
enum _SOCKET_TYPE {
UNKNOWN_SOCKET=0,
TCP_SOCKET=6,
UDP_SOCKET=17,
TLS_SOCKET=56,
SCTP_SOCKET=132,
TLS_SCTP_SOCKET=133,
DTLS_SOCKET=250,
TCP_SOCKET_PROXY=253,
TENTATIVE_SCTP_SOCKET=254,
TENTATIVE_TCP_SOCKET=255
UNKNOWN_SOCKET = 0,
TCP_SOCKET = 6,
UDP_SOCKET = 17,
TLS_SOCKET = 56,
SCTP_SOCKET = 132,
TLS_SCTP_SOCKET = 133,
DTLS_SOCKET = 250,
TCP_SOCKET_PROXY = 253,
TENTATIVE_SCTP_SOCKET = 254,
TENTATIVE_TCP_SOCKET = 255
};
typedef enum _SOCKET_TYPE SOCKET_TYPE;
enum _SOCKET_APP_TYPE {
UNKNOWN_APP_SOCKET,
CLIENT_SOCKET,
HTTP_CLIENT_SOCKET,
HTTPS_CLIENT_SOCKET,
RELAY_SOCKET,
RELAY_RTCP_SOCKET,
TCP_CLIENT_DATA_SOCKET,
TCP_RELAY_DATA_SOCKET,
LISTENER_SOCKET
UNKNOWN_APP_SOCKET,
CLIENT_SOCKET,
HTTP_CLIENT_SOCKET,
HTTPS_CLIENT_SOCKET,
RELAY_SOCKET,
RELAY_RTCP_SOCKET,
TCP_CLIENT_DATA_SOCKET,
TCP_RELAY_DATA_SOCKET,
LISTENER_SOCKET
};
typedef enum _SOCKET_APP_TYPE SOCKET_APP_TYPE;
@ -144,10 +144,10 @@ typedef void *ioa_network_buffer_handle;
/* event data for net event */
typedef struct _ioa_net_data {
ioa_addr src_addr;
ioa_network_buffer_handle nbh;
int recv_ttl;
int recv_tos;
ioa_addr src_addr;
ioa_network_buffer_handle nbh;
int recv_ttl;
int recv_tos;
} ioa_net_data;
/* Callback on TCP connection completion */
@ -163,27 +163,27 @@ typedef struct _realm_options_t realm_options_t;
//////// IP White/black listing ///////////
struct _ip_range {
char str[257];
char realm[513];
ioa_addr_range enc;
char str[257];
char realm[513];
ioa_addr_range enc;
};
typedef struct _ip_range ip_range_t;
struct _ip_range_list {
ip_range_t *rs;
size_t ranges_number;
ip_range_t *rs;
size_t ranges_number;
};
typedef struct _ip_range_list ip_range_list_t;
void ioa_lock_whitelist(ioa_engine_handle e);
void ioa_unlock_whitelist(ioa_engine_handle e);
const ip_range_list_t* ioa_get_whitelist(ioa_engine_handle e);
const ip_range_list_t *ioa_get_whitelist(ioa_engine_handle e);
void ioa_lock_blacklist(ioa_engine_handle e);
void ioa_unlock_blacklist(ioa_engine_handle e);
const ip_range_list_t* ioa_get_blacklist(ioa_engine_handle e);
const ip_range_list_t *ioa_get_blacklist(ioa_engine_handle e);
////////////////////////////////////////////
@ -215,7 +215,8 @@ void turn_report_session_usage(void *session, int force_invalid);
* the function must work correctly when chnum=0
* (when no hint information is available).
*/
typedef void (*ioa_net_event_handler)(ioa_socket_handle s, int event_type, ioa_net_data *data, void *ctx, int can_resume);
typedef void (*ioa_net_event_handler)(ioa_socket_handle s, int event_type, ioa_net_data *data, void *ctx,
int can_resume);
/*
* Timer callback
@ -224,10 +225,17 @@ typedef void (*ioa_timer_event_handler)(ioa_engine_handle e, void *ctx);
/* timers */
ioa_timer_handle set_ioa_timer(ioa_engine_handle e, int secs, int ms, ioa_timer_event_handler cb, void *ctx, int persist, const char *txt);
ioa_timer_handle set_ioa_timer(ioa_engine_handle e, int secs, int ms, ioa_timer_event_handler cb, void *ctx,
int persist, const char *txt);
void stop_ioa_timer(ioa_timer_handle th);
void delete_ioa_timer(ioa_timer_handle th);
#define IOA_EVENT_DEL(E) do { if(E) { delete_ioa_timer(E); E = NULL; } } while(0)
#define IOA_EVENT_DEL(E) \
do { \
if (E) { \
delete_ioa_timer(E); \
E = NULL; \
} \
} while (0)
ioa_socket_handle create_unbound_relay_ioa_socket(ioa_engine_handle e, int family, SOCKET_TYPE st, SOCKET_APP_TYPE sat);
@ -239,13 +247,13 @@ void inc_ioa_socket_ref_counter(ioa_socket_handle s);
* event_port == 0: reserve rtcp;
* even_port == +1: reserve and bind rtcp.
*/
int create_relay_ioa_sockets(ioa_engine_handle e, ioa_socket_handle client_s,
int address_family, uint8_t transport,
int even_port, ioa_socket_handle *rtp_s, ioa_socket_handle *rtcp_s,
uint64_t *out_reservation_token, int *err_code, const uint8_t **reason,
accept_cb acb, void *acbarg);
int create_relay_ioa_sockets(ioa_engine_handle e, ioa_socket_handle client_s, int address_family, uint8_t transport,
int even_port, ioa_socket_handle *rtp_s, ioa_socket_handle *rtcp_s,
uint64_t *out_reservation_token, int *err_code, const uint8_t **reason, accept_cb acb,
void *acbarg);
ioa_socket_handle ioa_create_connecting_tcp_relay_socket(ioa_socket_handle s, ioa_addr *peer_addr, connect_cb cb, void *arg);
ioa_socket_handle ioa_create_connecting_tcp_relay_socket(ioa_socket_handle s, ioa_addr *peer_addr, connect_cb cb,
void *arg);
int get_ioa_socket_from_reservation(ioa_engine_handle e, uint64_t in_reservation_token, ioa_socket_handle *s);
@ -253,26 +261,34 @@ int get_ioa_socket_address_family(ioa_socket_handle s);
int is_stream_socket(int st);
int is_tcp_socket(int st);
int is_sctp_socket(int st);
const char* socket_type_name(SOCKET_TYPE st);
const char* get_ioa_socket_cipher(ioa_socket_handle s);
const char* get_ioa_socket_ssl_method(ioa_socket_handle s);
const char *socket_type_name(SOCKET_TYPE st);
const char *get_ioa_socket_cipher(ioa_socket_handle s);
const char *get_ioa_socket_ssl_method(ioa_socket_handle s);
SOCKET_TYPE get_ioa_socket_type(ioa_socket_handle s);
SOCKET_APP_TYPE get_ioa_socket_app_type(ioa_socket_handle s);
const char* get_ioa_socket_tls_method(ioa_socket_handle s);
const char* get_ioa_socket_tls_cipher(ioa_socket_handle s);
const char *get_ioa_socket_tls_method(ioa_socket_handle s);
const char *get_ioa_socket_tls_cipher(ioa_socket_handle s);
void set_ioa_socket_app_type(ioa_socket_handle s, SOCKET_APP_TYPE sat);
ioa_addr* get_local_addr_from_ioa_socket(ioa_socket_handle s);
ioa_addr* get_remote_addr_from_ioa_socket(ioa_socket_handle s);
ioa_addr *get_local_addr_from_ioa_socket(ioa_socket_handle s);
ioa_addr *get_remote_addr_from_ioa_socket(ioa_socket_handle s);
int get_local_mtu_ioa_socket(ioa_socket_handle s);
ts_ur_super_session *get_ioa_socket_session(ioa_socket_handle s);
void set_ioa_socket_session(ioa_socket_handle s, ts_ur_super_session *ss);
void clear_ioa_socket_session_if(ioa_socket_handle s, void *ss);
tcp_connection *get_ioa_socket_sub_session(ioa_socket_handle s);
void set_ioa_socket_sub_session(ioa_socket_handle s, tcp_connection *tc);
int register_callback_on_ioa_socket(ioa_engine_handle e, ioa_socket_handle s, int event_type, ioa_net_event_handler cb, void *ctx, int clean_preexisting);
int send_data_from_ioa_socket_nbh(ioa_socket_handle s, ioa_addr* dest_addr, ioa_network_buffer_handle nbh, int ttl, int tos, int *skip);
int register_callback_on_ioa_socket(ioa_engine_handle e, ioa_socket_handle s, int event_type, ioa_net_event_handler cb,
void *ctx, int clean_preexisting);
int send_data_from_ioa_socket_nbh(ioa_socket_handle s, ioa_addr *dest_addr, ioa_network_buffer_handle nbh, int ttl,
int tos, int *skip);
void close_ioa_socket(ioa_socket_handle s);
#define IOA_CLOSE_SOCKET(S) do { if(S) { close_ioa_socket(S); S = NULL; } } while(0)
#define IOA_CLOSE_SOCKET(S) \
do { \
if (S) { \
close_ioa_socket(S); \
S = NULL; \
} \
} while (0)
ioa_socket_handle detach_ioa_socket(ioa_socket_handle s);
void detach_socket_net_data(ioa_socket_handle s);
int set_df_on_ioa_socket(ioa_socket_handle s, int value);
@ -283,23 +299,19 @@ void close_ioa_socket_after_processing_if_necessary(ioa_socket_handle s);
////////////////// Base64 /////////////////////////////
char *base64_encode(const unsigned char *data,
size_t input_length,
size_t *output_length);
char *base64_encode(const unsigned char *data, size_t input_length, size_t *output_length);
void build_base64_decoding_table(void);
unsigned char *base64_decode(const char *data,
size_t input_length,
size_t *output_length);
unsigned char *base64_decode(const char *data, size_t input_length, size_t *output_length);
///////////// Realm ///////////////////
void get_default_realm_options(realm_options_t* ro);
int get_realm_options_by_origin(char *origin, realm_options_t* ro);
void get_realm_options_by_name(char *realm, realm_options_t* ro);
int get_canonic_origin(const char* o, char *co, int sz);
int get_default_protocol_port(const char* scheme, size_t slen);
void get_default_realm_options(realm_options_t *ro);
int get_realm_options_by_origin(char *origin, realm_options_t *ro);
void get_realm_options_by_name(char *realm, realm_options_t *ro);
int get_canonic_origin(const char *o, char *co, int sz);
int get_default_protocol_port(const char *scheme, size_t slen);
///////////// HTTP ////////////////////

View File

@ -29,35 +29,35 @@
#include "khash.h"
KHASH_MAP_INIT_INT(32, char)
int main() {
int ret, is_missing;
khiter_t k;
khash_t(32) *h = kh_init(32);
k = kh_put(32, h, 5, &ret);
kh_value(h, k) = 10;
k = kh_get(32, h, 10);
is_missing = (k == kh_end(h));
k = kh_get(32, h, 5);
kh_del(32, h, k);
for (k = kh_begin(h); k != kh_end(h); ++k)
if (kh_exist(h, k)) kh_value(h, k) = 1;
kh_destroy(32, h);
return 0;
int ret, is_missing;
khiter_t k;
khash_t(32) *h = kh_init(32);
k = kh_put(32, h, 5, &ret);
kh_value(h, k) = 10;
k = kh_get(32, h, 10);
is_missing = (k == kh_end(h));
k = kh_get(32, h, 5);
kh_del(32, h, k);
for (k = kh_begin(h); k != kh_end(h); ++k)
if (kh_exist(h, k)) kh_value(h, k) = 1;
kh_destroy(32, h);
return 0;
}
*/
/*
2013-05-02 (0.2.8):
* Use quadratic probing. When the capacity is power of 2, stepping function
i*(i+1)/2 guarantees to traverse each bucket. It is better than double
hashing on cache performance and is more robust than linear probing.
* Use quadratic probing. When the capacity is power of 2, stepping function
i*(i+1)/2 guarantees to traverse each bucket. It is better than double
hashing on cache performance and is more robust than linear probing.
In theory, double hashing should be more robust than quadratic probing.
However, my implementation is probably not for large hash tables, because
the second hash function is closely tied to the first hash function,
which reduce the effectiveness of double hashing.
In theory, double hashing should be more robust than quadratic probing.
However, my implementation is probably not for large hash tables, because
the second hash function is closely tied to the first hash function,
which reduce the effectiveness of double hashing.
Reference: http://research.cs.vt.edu/AVresearch/hashing/quadratic.php
Reference: http://research.cs.vt.edu/AVresearch/hashing/quadratic.php
2011-12-29 (0.2.7):
@ -65,18 +65,18 @@ int main() {
2011-09-16 (0.2.6):
* The capacity is a power of 2. This seems to dramatically improve the
speed for simple keys. Thank Zilong Tan for the suggestion. Reference:
* The capacity is a power of 2. This seems to dramatically improve the
speed for simple keys. Thank Zilong Tan for the suggestion. Reference:
- http://code.google.com/p/ulib/
- http://nothings.org/computer/judy/
- http://code.google.com/p/ulib/
- http://nothings.org/computer/judy/
* Allow to optionally use linear probing which usually has better
performance for random input. Double hashing is still the default as it
is more robust to certain non-random input.
* Allow to optionally use linear probing which usually has better
performance for random input. Double hashing is still the default as it
is more robust to certain non-random input.
* Added Wang's integer hash function (not used by default). This hash
function is more robust to certain non-random input.
* Added Wang's integer hash function (not used by default). This hash
function is more robust to certain non-random input.
2011-02-14 (0.2.5):
@ -88,32 +88,31 @@ int main() {
2008-09-19 (0.2.3):
* Corrected the example
* Improved interfaces
* Corrected the example
* Improved interfaces
2008-09-11 (0.2.2):
* Improved speed a little in kh_put()
* Improved speed a little in kh_put()
2008-09-10 (0.2.1):
* Added kh_clear()
* Fixed a compiling error
* Added kh_clear()
* Fixed a compiling error
2008-09-02 (0.2.0):
* Changed to token concatenation which increases flexibility.
* Changed to token concatenation which increases flexibility.
2008-08-31 (0.1.2):
* Fixed a bug in kh_get(), which has not been tested previously.
* Fixed a bug in kh_get(), which has not been tested previously.
2008-08-31 (0.1.1):
* Added destructor
* Added destructor
*/
#ifndef __AC_KHASH_H
#define __AC_KHASH_H
@ -125,9 +124,9 @@ int main() {
#define AC_VERSION_KHASH_H "0.2.8"
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
/* compiler specific configuration */
@ -153,7 +152,7 @@ typedef unsigned long long khint64_t;
#ifndef klib_unused
#if (defined __clang__ && __clang_major__ >= 3) || (defined __GNUC__ && __GNUC__ >= 3)
#define klib_unused __attribute__ ((__unused__))
#define klib_unused __attribute__((__unused__))
#else
#define klib_unused
#endif
@ -162,28 +161,29 @@ typedef unsigned long long khint64_t;
typedef khint32_t khint_t;
typedef khint_t khiter_t;
#define __ac_isempty(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&2)
#define __ac_isdel(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&1)
#define __ac_iseither(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&3)
#define __ac_set_isdel_false(flag, i) (flag[i>>4]&=~(1ul<<((i&0xfU)<<1)))
#define __ac_set_isempty_false(flag, i) (flag[i>>4]&=~(2ul<<((i&0xfU)<<1)))
#define __ac_set_isboth_false(flag, i) (flag[i>>4]&=~(3ul<<((i&0xfU)<<1)))
#define __ac_set_isdel_true(flag, i) (flag[i>>4]|=1ul<<((i&0xfU)<<1))
#define __ac_isempty(flag, i) ((flag[i >> 4] >> ((i & 0xfU) << 1)) & 2)
#define __ac_isdel(flag, i) ((flag[i >> 4] >> ((i & 0xfU) << 1)) & 1)
#define __ac_iseither(flag, i) ((flag[i >> 4] >> ((i & 0xfU) << 1)) & 3)
#define __ac_set_isdel_false(flag, i) (flag[i >> 4] &= ~(1ul << ((i & 0xfU) << 1)))
#define __ac_set_isempty_false(flag, i) (flag[i >> 4] &= ~(2ul << ((i & 0xfU) << 1)))
#define __ac_set_isboth_false(flag, i) (flag[i >> 4] &= ~(3ul << ((i & 0xfU) << 1)))
#define __ac_set_isdel_true(flag, i) (flag[i >> 4] |= 1ul << ((i & 0xfU) << 1))
#define __ac_fsize(m) ((m) < 16? 1 : (m)>>4)
#define __ac_fsize(m) ((m) < 16 ? 1 : (m) >> 4)
#ifndef kroundup32
#define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x))
#define kroundup32(x) \
(--(x), (x) |= (x) >> 1, (x) |= (x) >> 2, (x) |= (x) >> 4, (x) |= (x) >> 8, (x) |= (x) >> 16, ++(x))
#endif
#ifndef kcalloc
#define kcalloc(N,Z) calloc(N,Z)
#define kcalloc(N, Z) calloc(N, Z)
#endif
#ifndef kmalloc
#define kmalloc(Z) malloc(Z)
#endif
#ifndef krealloc
#define krealloc(P,Z) realloc(P,Z)
#define krealloc(P, Z) realloc(P, Z)
#endif
#ifndef kfree
#define kfree(P) free(P)
@ -191,179 +191,211 @@ typedef khint_t khiter_t;
static const double __ac_HASH_UPPER = 0.77;
#define __KHASH_TYPE(name, khkey_t, khval_t) \
typedef struct kh_##name##_s { \
khint_t n_buckets, size, n_occupied, upper_bound; \
khint32_t *flags; \
khkey_t *keys; \
khval_t *vals; \
} kh_##name##_t;
#define __KHASH_TYPE(name, khkey_t, khval_t) \
typedef struct kh_##name##_s { \
khint_t n_buckets, size, n_occupied, upper_bound; \
khint32_t *flags; \
khkey_t *keys; \
khval_t *vals; \
} kh_##name##_t;
#define __KHASH_PROTOTYPES(name, khkey_t, khval_t) \
extern kh_##name##_t *kh_init_##name(void); \
extern void kh_destroy_##name(kh_##name##_t *h); \
extern void kh_clear_##name(kh_##name##_t *h); \
extern khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key); \
extern int kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets); \
extern khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret); \
extern void kh_del_##name(kh_##name##_t *h, khint_t x);
#define __KHASH_PROTOTYPES(name, khkey_t, khval_t) \
extern kh_##name##_t *kh_init_##name(void); \
extern void kh_destroy_##name(kh_##name##_t *h); \
extern void kh_clear_##name(kh_##name##_t *h); \
extern khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key); \
extern int kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets); \
extern khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret); \
extern void kh_del_##name(kh_##name##_t *h, khint_t x);
#define __KHASH_IMPL(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \
SCOPE kh_##name##_t *kh_init_##name(void) { \
return (kh_##name##_t*)kcalloc(1, sizeof(kh_##name##_t)); \
} \
SCOPE void kh_destroy_##name(kh_##name##_t *h) \
{ \
if (h) { \
kfree((void *)h->keys); kfree(h->flags); \
kfree((void *)h->vals); \
kfree(h); \
} \
} \
SCOPE void kh_clear_##name(kh_##name##_t *h) \
{ \
if (h && h->flags) { \
memset(h->flags, 0xaa, __ac_fsize(h->n_buckets) * sizeof(khint32_t)); \
h->size = h->n_occupied = 0; \
} \
} \
SCOPE khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key) \
{ \
if (h->n_buckets) { \
khint_t k, i, last, mask, step = 0; \
mask = h->n_buckets - 1; \
k = __hash_func(key); i = k & mask; \
last = i; \
while (!__ac_isempty(h->flags, i) && (__ac_isdel(h->flags, i) || !__hash_equal(h->keys[i], key))) { \
i = (i + (++step)) & mask; \
if (i == last) return h->n_buckets; \
} \
return __ac_iseither(h->flags, i)? h->n_buckets : i; \
} else return 0; \
} \
SCOPE int kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets) \
{ /* This function uses 0.25*n_buckets bytes of working space instead of [sizeof(key_t+val_t)+.25]*n_buckets. */ \
khint32_t *new_flags = 0; \
khint_t j = 1; \
{ \
kroundup32(new_n_buckets); \
if (new_n_buckets < 4) new_n_buckets = 4; \
if (h->size >= (khint_t)(new_n_buckets * __ac_HASH_UPPER + 0.5)) j = 0; /* requested size is too small */ \
else { /* hash table size to be changed (shrink or expand); rehash */ \
new_flags = (khint32_t*)kmalloc(__ac_fsize(new_n_buckets) * sizeof(khint32_t)); \
if (!new_flags) return -1; \
memset(new_flags, 0xaa, __ac_fsize(new_n_buckets) * sizeof(khint32_t)); \
if (h->n_buckets < new_n_buckets) { /* expand */ \
khkey_t *new_keys = (khkey_t*)krealloc((void *)h->keys, new_n_buckets * sizeof(khkey_t)); \
if (!new_keys) { kfree(new_flags); return -1; } \
h->keys = new_keys; \
if (kh_is_map) { \
khval_t *new_vals = (khval_t*)krealloc((void *)h->vals, new_n_buckets * sizeof(khval_t)); \
if (!new_vals) { kfree(new_flags); return -1; } \
h->vals = new_vals; \
} \
} /* otherwise shrink */ \
} \
} \
if (j) { /* rehashing is needed */ \
for (j = 0; j != h->n_buckets; ++j) { \
if (__ac_iseither(h->flags, j) == 0) { \
khkey_t key = h->keys[j]; \
khval_t val; \
khint_t new_mask; \
new_mask = new_n_buckets - 1; \
if (kh_is_map) val = h->vals[j]; \
__ac_set_isdel_true(h->flags, j); \
while (1) { /* kick-out process; sort of like in Cuckoo hashing */ \
khint_t k, i, step = 0; \
k = __hash_func(key); \
i = k & new_mask; \
while (!__ac_isempty(new_flags, i)) i = (i + (++step)) & new_mask; \
__ac_set_isempty_false(new_flags, i); \
if (i < h->n_buckets && __ac_iseither(h->flags, i) == 0) { /* kick out the existing element */ \
{ khkey_t tmp = h->keys[i]; h->keys[i] = key; key = tmp; } \
if (kh_is_map) { khval_t tmp = h->vals[i]; h->vals[i] = val; val = tmp; } \
__ac_set_isdel_true(h->flags, i); /* mark it as deleted in the old hash table */ \
} else { /* write the element and jump out of the loop */ \
h->keys[i] = key; \
if (kh_is_map) h->vals[i] = val; \
break; \
} \
} \
} \
} \
if (h->n_buckets > new_n_buckets) { /* shrink the hash table */ \
h->keys = (khkey_t*)krealloc((void *)h->keys, new_n_buckets * sizeof(khkey_t)); \
if (kh_is_map) h->vals = (khval_t*)krealloc((void *)h->vals, new_n_buckets * sizeof(khval_t)); \
} \
kfree(h->flags); /* free the working space */ \
h->flags = new_flags; \
h->n_buckets = new_n_buckets; \
h->n_occupied = h->size; \
h->upper_bound = (khint_t)(h->n_buckets * __ac_HASH_UPPER + 0.5); \
} \
return 0; \
} \
SCOPE khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret) \
{ \
khint_t x; \
if (h->n_occupied >= h->upper_bound) { /* update the hash table */ \
if (h->n_buckets > (h->size<<1)) { \
if (kh_resize_##name(h, h->n_buckets - 1) < 0) { /* clear "deleted" elements */ \
*ret = -1; return h->n_buckets; \
} \
} else if (kh_resize_##name(h, h->n_buckets + 1) < 0) { /* expand the hash table */ \
*ret = -1; return h->n_buckets; \
} \
} /* TODO: to implement automatically shrinking; resize() already support shrinking */ \
{ \
khint_t k, i, site, last, mask = h->n_buckets - 1, step = 0; \
x = site = h->n_buckets; k = __hash_func(key); i = k & mask; \
if (__ac_isempty(h->flags, i)) x = i; /* for speed up */ \
else { \
last = i; \
while (!__ac_isempty(h->flags, i) && (__ac_isdel(h->flags, i) || !__hash_equal(h->keys[i], key))) { \
if (__ac_isdel(h->flags, i)) site = i; \
i = (i + (++step)) & mask; \
if (i == last) { x = site; break; } \
} \
if (x == h->n_buckets) { \
if (__ac_isempty(h->flags, i) && site != h->n_buckets) x = site; \
else x = i; \
} \
} \
} \
if (__ac_isempty(h->flags, x)) { /* not present at all */ \
h->keys[x] = key; \
__ac_set_isboth_false(h->flags, x); \
++h->size; ++h->n_occupied; \
*ret = 1; \
} else if (__ac_isdel(h->flags, x)) { /* deleted */ \
h->keys[x] = key; \
__ac_set_isboth_false(h->flags, x); \
++h->size; \
*ret = 2; \
} else *ret = 0; /* Don't touch h->keys[x] if present and not deleted */ \
return x; \
} \
SCOPE void kh_del_##name(kh_##name##_t *h, khint_t x) \
{ \
if (x != h->n_buckets && !__ac_iseither(h->flags, x)) { \
__ac_set_isdel_true(h->flags, x); \
--h->size; \
} \
}
#define __KHASH_IMPL(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \
SCOPE kh_##name##_t *kh_init_##name(void) { return (kh_##name##_t *)kcalloc(1, sizeof(kh_##name##_t)); } \
SCOPE void kh_destroy_##name(kh_##name##_t *h) { \
if (h) { \
kfree((void *)h->keys); \
kfree(h->flags); \
kfree((void *)h->vals); \
kfree(h); \
} \
} \
SCOPE void kh_clear_##name(kh_##name##_t *h) { \
if (h && h->flags) { \
memset(h->flags, 0xaa, __ac_fsize(h->n_buckets) * sizeof(khint32_t)); \
h->size = h->n_occupied = 0; \
} \
} \
SCOPE khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key) { \
if (h->n_buckets) { \
khint_t k, i, last, mask, step = 0; \
mask = h->n_buckets - 1; \
k = __hash_func(key); \
i = k & mask; \
last = i; \
while (!__ac_isempty(h->flags, i) && (__ac_isdel(h->flags, i) || !__hash_equal(h->keys[i], key))) { \
i = (i + (++step)) & mask; \
if (i == last) \
return h->n_buckets; \
} \
return __ac_iseither(h->flags, i) ? h->n_buckets : i; \
} else \
return 0; \
} \
SCOPE int kh_resize_##name(kh_##name##_t *h, \
khint_t new_n_buckets) { /* This function uses 0.25*n_buckets bytes of working space \
instead of [sizeof(key_t+val_t)+.25]*n_buckets. */ \
khint32_t *new_flags = 0; \
khint_t j = 1; \
{ \
kroundup32(new_n_buckets); \
if (new_n_buckets < 4) \
new_n_buckets = 4; \
if (h->size >= (khint_t)(new_n_buckets * __ac_HASH_UPPER + 0.5)) \
j = 0; /* requested size is too small */ \
else { /* hash table size to be changed (shrink or expand); rehash */ \
new_flags = (khint32_t *)kmalloc(__ac_fsize(new_n_buckets) * sizeof(khint32_t)); \
if (!new_flags) \
return -1; \
memset(new_flags, 0xaa, __ac_fsize(new_n_buckets) * sizeof(khint32_t)); \
if (h->n_buckets < new_n_buckets) { /* expand */ \
khkey_t *new_keys = (khkey_t *)krealloc((void *)h->keys, new_n_buckets * sizeof(khkey_t)); \
if (!new_keys) { \
kfree(new_flags); \
return -1; \
} \
h->keys = new_keys; \
if (kh_is_map) { \
khval_t *new_vals = (khval_t *)krealloc((void *)h->vals, new_n_buckets * sizeof(khval_t)); \
if (!new_vals) { \
kfree(new_flags); \
return -1; \
} \
h->vals = new_vals; \
} \
} /* otherwise shrink */ \
} \
} \
if (j) { /* rehashing is needed */ \
for (j = 0; j != h->n_buckets; ++j) { \
if (__ac_iseither(h->flags, j) == 0) { \
khkey_t key = h->keys[j]; \
khval_t val; \
khint_t new_mask; \
new_mask = new_n_buckets - 1; \
if (kh_is_map) \
val = h->vals[j]; \
__ac_set_isdel_true(h->flags, j); \
while (1) { /* kick-out process; sort of like in Cuckoo hashing */ \
khint_t k, i, step = 0; \
k = __hash_func(key); \
i = k & new_mask; \
while (!__ac_isempty(new_flags, i)) \
i = (i + (++step)) & new_mask; \
__ac_set_isempty_false(new_flags, i); \
if (i < h->n_buckets && __ac_iseither(h->flags, i) == 0) { /* kick out the existing element */ \
{ \
khkey_t tmp = h->keys[i]; \
h->keys[i] = key; \
key = tmp; \
} \
if (kh_is_map) { \
khval_t tmp = h->vals[i]; \
h->vals[i] = val; \
val = tmp; \
} \
__ac_set_isdel_true(h->flags, i); /* mark it as deleted in the old hash table */ \
} else { /* write the element and jump out of the loop */ \
h->keys[i] = key; \
if (kh_is_map) \
h->vals[i] = val; \
break; \
} \
} \
} \
} \
if (h->n_buckets > new_n_buckets) { /* shrink the hash table */ \
h->keys = (khkey_t *)krealloc((void *)h->keys, new_n_buckets * sizeof(khkey_t)); \
if (kh_is_map) \
h->vals = (khval_t *)krealloc((void *)h->vals, new_n_buckets * sizeof(khval_t)); \
} \
kfree(h->flags); /* free the working space */ \
h->flags = new_flags; \
h->n_buckets = new_n_buckets; \
h->n_occupied = h->size; \
h->upper_bound = (khint_t)(h->n_buckets * __ac_HASH_UPPER + 0.5); \
} \
return 0; \
} \
SCOPE khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret) { \
khint_t x; \
if (h->n_occupied >= h->upper_bound) { /* update the hash table */ \
if (h->n_buckets > (h->size << 1)) { \
if (kh_resize_##name(h, h->n_buckets - 1) < 0) { /* clear "deleted" elements */ \
*ret = -1; \
return h->n_buckets; \
} \
} else if (kh_resize_##name(h, h->n_buckets + 1) < 0) { /* expand the hash table */ \
*ret = -1; \
return h->n_buckets; \
} \
} /* TODO: to implement automatically shrinking; resize() already support shrinking */ \
{ \
khint_t k, i, site, last, mask = h->n_buckets - 1, step = 0; \
x = site = h->n_buckets; \
k = __hash_func(key); \
i = k & mask; \
if (__ac_isempty(h->flags, i)) \
x = i; /* for speed up */ \
else { \
last = i; \
while (!__ac_isempty(h->flags, i) && (__ac_isdel(h->flags, i) || !__hash_equal(h->keys[i], key))) { \
if (__ac_isdel(h->flags, i)) \
site = i; \
i = (i + (++step)) & mask; \
if (i == last) { \
x = site; \
break; \
} \
} \
if (x == h->n_buckets) { \
if (__ac_isempty(h->flags, i) && site != h->n_buckets) \
x = site; \
else \
x = i; \
} \
} \
} \
if (__ac_isempty(h->flags, x)) { /* not present at all */ \
h->keys[x] = key; \
__ac_set_isboth_false(h->flags, x); \
++h->size; \
++h->n_occupied; \
*ret = 1; \
} else if (__ac_isdel(h->flags, x)) { /* deleted */ \
h->keys[x] = key; \
__ac_set_isboth_false(h->flags, x); \
++h->size; \
*ret = 2; \
} else \
*ret = 0; /* Don't touch h->keys[x] if present and not deleted */ \
return x; \
} \
SCOPE void kh_del_##name(kh_##name##_t *h, khint_t x) { \
if (x != h->n_buckets && !__ac_iseither(h->flags, x)) { \
__ac_set_isdel_true(h->flags, x); \
--h->size; \
} \
}
#define KHASH_DECLARE(name, khkey_t, khval_t) \
__KHASH_TYPE(name, khkey_t, khval_t) \
__KHASH_PROTOTYPES(name, khkey_t, khval_t)
#define KHASH_DECLARE(name, khkey_t, khval_t) \
__KHASH_TYPE(name, khkey_t, khval_t) \
__KHASH_PROTOTYPES(name, khkey_t, khval_t)
#define KHASH_INIT2(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \
__KHASH_TYPE(name, khkey_t, khval_t) \
__KHASH_IMPL(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal)
#define KHASH_INIT2(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \
__KHASH_TYPE(name, khkey_t, khval_t) \
__KHASH_IMPL(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal)
#define KHASH_INIT(name, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \
KHASH_INIT2(name, static kh_inline klib_unused, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal)
#define KHASH_INIT(name, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \
KHASH_INIT2(name, static kh_inline klib_unused, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal)
/* --- BEGIN OF HASH FUNCTIONS --- */
@ -382,7 +414,7 @@ static const double __ac_HASH_UPPER = 0.77;
@param key The integer [khint64_t]
@return The hash value [khint_t]
*/
#define kh_int64_hash_func(key) (khint32_t)((key)>>33^(key)^(key)<<11)
#define kh_int64_hash_func(key) (khint32_t)((key) >> 33 ^ (key) ^ (key) << 11)
/*! @function
@abstract 64-bit integer comparison function
*/
@ -392,11 +424,12 @@ static const double __ac_HASH_UPPER = 0.77;
@param s Pointer to a null terminated string
@return The hash value
*/
static kh_inline khint_t __ac_X31_hash_string(const char *s)
{
khint_t h = (khint_t)*s;
if (h) for (++s ; *s; ++s) h = (h << 5) - h + (khint_t)*s;
return h;
static kh_inline khint_t __ac_X31_hash_string(const char *s) {
khint_t h = (khint_t)*s;
if (h)
for (++s; *s; ++s)
h = (h << 5) - h + (khint_t)*s;
return h;
}
/*! @function
@abstract Another interface to const char* hash function
@ -409,15 +442,14 @@ static kh_inline khint_t __ac_X31_hash_string(const char *s)
*/
#define kh_str_hash_equal(a, b) (strcmp(a, b) == 0)
static kh_inline khint_t __ac_Wang_hash(khint_t key)
{
key += ~(key << 15);
key ^= (key >> 10);
key += (key << 3);
key ^= (key >> 6);
key += ~(key << 11);
key ^= (key >> 16);
return key;
static kh_inline khint_t __ac_Wang_hash(khint_t key) {
key += ~(key << 15);
key ^= (key >> 10);
key += (key << 3);
key ^= (key >> 6);
key += ~(key << 11);
key ^= (key >> 16);
return key;
}
#define kh_int_hash_func2(key) __ac_Wang_hash((khint_t)key)
@ -468,7 +500,7 @@ static kh_inline khint_t __ac_Wang_hash(khint_t key)
@param r Extra return code: -1 if the operation failed;
0 if the key is present in the hash table;
1 if the bucket is empty (never used); 2 if the element in
the bucket has been deleted [int*]
the bucket has been deleted [int*]
@return Iterator to the inserted element [khint_t]
*/
#define kh_put(name, h, k, r) kh_put_##name(h, k, r)
@ -555,13 +587,17 @@ static kh_inline khint_t __ac_Wang_hash(khint_t key)
@param vvar Variable to which value will be assigned
@param code Block of code to execute
*/
#define kh_foreach(h, kvar, vvar, code) { khint_t __i; \
for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \
if (!kh_exist(h,__i)) continue; \
(kvar) = kh_key(h,__i); \
(vvar) = kh_val(h,__i); \
code; \
} }
#define kh_foreach(h, kvar, vvar, code) \
{ \
khint_t __i; \
for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \
if (!kh_exist(h, __i)) \
continue; \
(kvar) = kh_key(h, __i); \
(vvar) = kh_val(h, __i); \
code; \
} \
}
/*! @function
@abstract Iterate over the values in the hash table
@ -569,12 +605,16 @@ static kh_inline khint_t __ac_Wang_hash(khint_t key)
@param vvar Variable to which value will be assigned
@param code Block of code to execute
*/
#define kh_foreach_value(h, vvar, code) { khint_t __i; \
for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \
if (!kh_exist(h,__i)) continue; \
(vvar) = kh_val(h,__i); \
code; \
} }
#define kh_foreach_value(h, vvar, code) \
{ \
khint_t __i; \
for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \
if (!kh_exist(h, __i)) \
continue; \
(vvar) = kh_val(h, __i); \
code; \
} \
}
/* More convenient interfaces */
@ -582,46 +622,41 @@ static kh_inline khint_t __ac_Wang_hash(khint_t key)
@abstract Instantiate a hash set containing integer keys
@param name Name of the hash table [symbol]
*/
#define KHASH_SET_INIT_INT(name) \
KHASH_INIT(name, khint32_t, char, 0, kh_int_hash_func, kh_int_hash_equal)
#define KHASH_SET_INIT_INT(name) KHASH_INIT(name, khint32_t, char, 0, kh_int_hash_func, kh_int_hash_equal)
/*! @function
@abstract Instantiate a hash map containing integer keys
@param name Name of the hash table [symbol]
@param khval_t Type of values [type]
*/
#define KHASH_MAP_INIT_INT(name, khval_t) \
KHASH_INIT(name, khint32_t, khval_t, 1, kh_int_hash_func, kh_int_hash_equal)
#define KHASH_MAP_INIT_INT(name, khval_t) KHASH_INIT(name, khint32_t, khval_t, 1, kh_int_hash_func, kh_int_hash_equal)
/*! @function
@abstract Instantiate a hash set containing 64-bit integer keys
@param name Name of the hash table [symbol]
*/
#define KHASH_SET_INIT_INT64(name) \
KHASH_INIT(name, khint64_t, char, 0, kh_int64_hash_func, kh_int64_hash_equal)
#define KHASH_SET_INIT_INT64(name) KHASH_INIT(name, khint64_t, char, 0, kh_int64_hash_func, kh_int64_hash_equal)
/*! @function
@abstract Instantiate a hash map containing 64-bit integer keys
@param name Name of the hash table [symbol]
@param khval_t Type of values [type]
*/
#define KHASH_MAP_INIT_INT64(name, khval_t) \
KHASH_INIT(name, khint64_t, khval_t, 1, kh_int64_hash_func, kh_int64_hash_equal)
#define KHASH_MAP_INIT_INT64(name, khval_t) \
KHASH_INIT(name, khint64_t, khval_t, 1, kh_int64_hash_func, kh_int64_hash_equal)
typedef const char *kh_cstr_t;
/*! @function
@abstract Instantiate a hash map containing const char* keys
@param name Name of the hash table [symbol]
*/
#define KHASH_SET_INIT_STR(name) \
KHASH_INIT(name, kh_cstr_t, char, 0, kh_str_hash_func, kh_str_hash_equal)
#define KHASH_SET_INIT_STR(name) KHASH_INIT(name, kh_cstr_t, char, 0, kh_str_hash_func, kh_str_hash_equal)
/*! @function
@abstract Instantiate a hash map containing const char* keys
@param name Name of the hash table [symbol]
@param khval_t Type of values [type]
*/
#define KHASH_MAP_INIT_STR(name, khval_t) \
KHASH_INIT(name, kh_cstr_t, khval_t, 1, kh_str_hash_func, kh_str_hash_equal)
#define KHASH_MAP_INIT_STR(name, khval_t) KHASH_INIT(name, kh_cstr_t, khval_t, 1, kh_str_hash_func, kh_str_hash_equal)
#endif /* __AC_KHASH_H */

File diff suppressed because it is too large Load Diff

View File

@ -50,13 +50,11 @@ typedef uintptr_t ur_map_value_type;
typedef void (*ur_map_del_func)(ur_map_value_type);
typedef int (*foreachcb_type)(ur_map_key_type key, ur_map_value_type value);
typedef int (*foreachcb_arg_type)(ur_map_key_type key,
ur_map_value_type value,
void *arg);
typedef int (*foreachcb_arg_type)(ur_map_key_type key, ur_map_value_type value, void *arg);
///////////// non-local map /////////////////////
ur_map* ur_map_create(void);
ur_map *ur_map_create(void);
/**
* @ret:
@ -64,7 +62,7 @@ ur_map* ur_map_create(void);
* -1 - error
*/
int ur_map_put(ur_map* map, ur_map_key_type key, ur_map_value_type value);
int ur_map_put(ur_map *map, ur_map_key_type key, ur_map_value_type value);
/**
* @ret:
@ -72,32 +70,32 @@ int ur_map_put(ur_map* map, ur_map_key_type key, ur_map_value_type value);
* 0 - not found
*/
int ur_map_get(const ur_map* map, ur_map_key_type key, ur_map_value_type *value);
int ur_map_get(const ur_map *map, ur_map_key_type key, ur_map_value_type *value);
/**
* @ret:
* 1 - success
* 0 - not found
*/
int ur_map_del(ur_map* map, ur_map_key_type key,ur_map_del_func delfunc);
int ur_map_del(ur_map *map, ur_map_key_type key, ur_map_del_func delfunc);
/**
* @ret:
* 1 - success
* 0 - not found
*/
int ur_map_exist(const ur_map* map, ur_map_key_type key);
int ur_map_exist(const ur_map *map, ur_map_key_type key);
void ur_map_free(ur_map** map);
void ur_map_free(ur_map **map);
size_t ur_map_size(const ur_map* map);
size_t ur_map_size(const ur_map *map);
int ur_map_foreach(ur_map* map, foreachcb_type func);
int ur_map_foreach(ur_map *map, foreachcb_type func);
int ur_map_foreach_arg(const ur_map* map, foreachcb_arg_type func, void* arg);
int ur_map_foreach_arg(const ur_map *map, foreachcb_arg_type func, void *arg);
int ur_map_lock(const ur_map* map);
int ur_map_unlock(const ur_map* map);
int ur_map_lock(const ur_map *map);
int ur_map_unlock(const ur_map *map);
///////////// "local" map /////////////////////
@ -105,15 +103,15 @@ int ur_map_unlock(const ur_map* map);
#define LM_MAP_ARRAY_SIZE (3)
typedef struct _lm_map_array {
ur_map_key_type main_keys[LM_MAP_ARRAY_SIZE];
ur_map_value_type main_values[LM_MAP_ARRAY_SIZE];
size_t extra_sz;
ur_map_key_type **extra_keys;
ur_map_value_type **extra_values;
ur_map_key_type main_keys[LM_MAP_ARRAY_SIZE];
ur_map_value_type main_values[LM_MAP_ARRAY_SIZE];
size_t extra_sz;
ur_map_key_type **extra_keys;
ur_map_value_type **extra_values;
} lm_map_array;
typedef struct _lm_map {
lm_map_array table[LM_MAP_HASH_SIZE];
lm_map_array table[LM_MAP_HASH_SIZE];
} lm_map;
void lm_map_init(lm_map *map);
@ -124,7 +122,7 @@ void lm_map_init(lm_map *map);
* -1 - error
*/
int lm_map_put(lm_map* map, ur_map_key_type key, ur_map_value_type value);
int lm_map_put(lm_map *map, ur_map_key_type key, ur_map_value_type value);
/**
* @ret:
@ -132,29 +130,29 @@ int lm_map_put(lm_map* map, ur_map_key_type key, ur_map_value_type value);
* 0 - not found
*/
int lm_map_get(const lm_map* map, ur_map_key_type key, ur_map_value_type *value);
int lm_map_get(const lm_map *map, ur_map_key_type key, ur_map_value_type *value);
/**
* @ret:
* 1 - success
* 0 - not found
*/
int lm_map_del(lm_map* map, ur_map_key_type key,ur_map_del_func delfunc);
int lm_map_del(lm_map *map, ur_map_key_type key, ur_map_del_func delfunc);
/**
* @ret:
* 1 - success
* 0 - not found
*/
int lm_map_exist(const lm_map* map, ur_map_key_type key);
int lm_map_exist(const lm_map *map, ur_map_key_type key);
void lm_map_clean(lm_map* map);
void lm_map_clean(lm_map *map);
size_t lm_map_size(const lm_map* map);
size_t lm_map_size(const lm_map *map);
int lm_map_foreach(lm_map* map, foreachcb_type func);
int lm_map_foreach(lm_map *map, foreachcb_type func);
int lm_map_foreach_arg(lm_map* map, foreachcb_arg_type func, void* arg);
int lm_map_foreach_arg(lm_map *map, foreachcb_arg_type func, void *arg);
//////////////// UR ADDR MAP //////////////////
@ -184,8 +182,8 @@ typedef struct _ur_addr_map ur_addr_map;
typedef void (*ur_addr_map_func)(ur_addr_map_value_type);
void ur_addr_map_init(ur_addr_map* map);
void ur_addr_map_clean(ur_addr_map* map);
void ur_addr_map_init(ur_addr_map *map);
void ur_addr_map_clean(ur_addr_map *map);
/**
* @ret:
@ -193,42 +191,42 @@ void ur_addr_map_clean(ur_addr_map* map);
* -1 - error
* if the addr key exists, the value is updated.
*/
int ur_addr_map_put(ur_addr_map* map, ioa_addr* key, ur_addr_map_value_type value);
int ur_addr_map_put(ur_addr_map *map, ioa_addr *key, ur_addr_map_value_type value);
/**
* @ret:
* 1 - success
* 0 - not found
*/
int ur_addr_map_get(const ur_addr_map* map, ioa_addr* key, ur_addr_map_value_type *value);
int ur_addr_map_get(const ur_addr_map *map, ioa_addr *key, ur_addr_map_value_type *value);
/**
* @ret:
* 1 - success
* 0 - not found
*/
int ur_addr_map_del(ur_addr_map* map, ioa_addr* key,ur_addr_map_func func);
int ur_addr_map_del(ur_addr_map *map, ioa_addr *key, ur_addr_map_func func);
/**
* @ret:
* 1 - success
* 0 - not found
*/
void ur_addr_map_foreach(ur_addr_map* map, ur_addr_map_func func);
void ur_addr_map_foreach(ur_addr_map *map, ur_addr_map_func func);
size_t ur_addr_map_num_elements(const ur_addr_map* map);
size_t ur_addr_map_size(const ur_addr_map* map);
size_t ur_addr_map_num_elements(const ur_addr_map *map);
size_t ur_addr_map_size(const ur_addr_map *map);
//////////////// UR STRING MAP //////////////////
typedef char* ur_string_map_key_type;
typedef void* ur_string_map_value_type;
typedef char *ur_string_map_key_type;
typedef void *ur_string_map_value_type;
struct _ur_string_map;
typedef struct _ur_string_map ur_string_map;
typedef void (*ur_string_map_func)(ur_string_map_value_type);
ur_string_map* ur_string_map_create(ur_string_map_func del_value_func);
ur_string_map *ur_string_map_create(ur_string_map_func del_value_func);
/**
* @ret:
@ -236,29 +234,29 @@ ur_string_map* ur_string_map_create(ur_string_map_func del_value_func);
* -1 - error
* if the string key exists, and the value is different, return error.
*/
int ur_string_map_put(ur_string_map* map, const ur_string_map_key_type key, ur_string_map_value_type value);
int ur_string_map_put(ur_string_map *map, const ur_string_map_key_type key, ur_string_map_value_type value);
/**
* @ret:
* 1 - success
* 0 - not found
*/
int ur_string_map_get(ur_string_map* map, const ur_string_map_key_type key, ur_string_map_value_type *value);
int ur_string_map_get(ur_string_map *map, const ur_string_map_key_type key, ur_string_map_value_type *value);
/**
* @ret:
* 1 - success
* 0 - not found
*/
int ur_string_map_del(ur_string_map* map, const ur_string_map_key_type key);
int ur_string_map_del(ur_string_map *map, const ur_string_map_key_type key);
void ur_string_map_clean(ur_string_map* map);
void ur_string_map_free(ur_string_map** map);
void ur_string_map_clean(ur_string_map *map);
void ur_string_map_free(ur_string_map **map);
size_t ur_string_map_size(const ur_string_map* map);
size_t ur_string_map_size(const ur_string_map *map);
int ur_string_map_lock(const ur_string_map* map);
int ur_string_map_unlock(const ur_string_map* map);
int ur_string_map_lock(const ur_string_map *map);
int ur_string_map_unlock(const ur_string_map *map);
////////////////////////////////////////////

View File

@ -47,7 +47,6 @@ struct _rtcp_map {
TURN_MUTEX_DECLARE(mutex)
};
typedef struct {
ioa_socket_handle s;
turn_time_t t;
@ -56,9 +55,7 @@ typedef struct {
////////////////////////////////////////////
static int rtcp_map_valid(const rtcp_map *map) {
return (map && (map->magic==MAGIC_RTCP_MAP) && map->map);
}
static int rtcp_map_valid(const rtcp_map *map) { return (map && (map->magic == MAGIC_RTCP_MAP) && map->map); }
typedef struct {
rtcp_token_type tokens[MAX_TOKEN_DEL];
@ -66,44 +63,40 @@ typedef struct {
turn_time_t t;
} timeout_check_arg_type;
static int timeout_check(ur_map_key_type key,
ur_map_value_type value,
void *arg) {
if(value && arg) {
timeout_check_arg_type *tcat=(timeout_check_arg_type*)arg;
rtcp_alloc_type* rat=(rtcp_alloc_type*)value;
if(turn_time_before(rat->t, tcat->t) && (tcat->tn<MAX_TOKEN_DEL)) {
tcat->tokens[(tcat->tn)++]=key;
static int timeout_check(ur_map_key_type key, ur_map_value_type value, void *arg) {
if (value && arg) {
timeout_check_arg_type *tcat = (timeout_check_arg_type *)arg;
rtcp_alloc_type *rat = (rtcp_alloc_type *)value;
if (turn_time_before(rat->t, tcat->t) && (tcat->tn < MAX_TOKEN_DEL)) {
tcat->tokens[(tcat->tn)++] = key;
}
}
return 0;
}
static void rtcp_alloc_free(ur_map_value_type value)
{
rtcp_alloc_type *at = (rtcp_alloc_type *)value;
if (at) {
IOA_CLOSE_SOCKET(at->s);
free(at);
}
static void rtcp_alloc_free(ur_map_value_type value) {
rtcp_alloc_type *at = (rtcp_alloc_type *)value;
if (at) {
IOA_CLOSE_SOCKET(at->s);
free(at);
}
}
static void rtcp_alloc_free_savefd(ur_map_value_type value)
{
rtcp_alloc_type *at = (rtcp_alloc_type *) value;
if (at) {
free(at);
}
static void rtcp_alloc_free_savefd(ur_map_value_type value) {
rtcp_alloc_type *at = (rtcp_alloc_type *)value;
if (at) {
free(at);
}
}
static int foreachcb_free(ur_map_key_type key, ur_map_value_type value) {
UNUSED_ARG(key);
if(value) {
if (value) {
rtcp_alloc_free(value);
}
return 0;
@ -114,70 +107,72 @@ static int foreachcb_free(ur_map_key_type key, ur_map_value_type value) {
* 1 - success
* 0 - not found
*/
static int rtcp_map_del(rtcp_map* map, rtcp_token_type token) {
if(!rtcp_map_valid(map)) return 0;
static int rtcp_map_del(rtcp_map *map, rtcp_token_type token) {
if (!rtcp_map_valid(map))
return 0;
else {
TURN_MUTEX_LOCK(&map->mutex);
int ret = ur_map_del(map->map,token,rtcp_alloc_free);
int ret = ur_map_del(map->map, token, rtcp_alloc_free);
TURN_MUTEX_UNLOCK(&map->mutex);
return ret;
}
}
static int rtcp_map_del_savefd(rtcp_map* map, rtcp_token_type token) {
if(!rtcp_map_valid(map)) return 0;
static int rtcp_map_del_savefd(rtcp_map *map, rtcp_token_type token) {
if (!rtcp_map_valid(map))
return 0;
else {
int ret = ur_map_del(map->map,token,rtcp_alloc_free_savefd);
int ret = ur_map_del(map->map, token, rtcp_alloc_free_savefd);
return ret;
}
}
static void rtcp_map_timeout_handler(ioa_engine_handle e, void* arg) {
static void rtcp_map_timeout_handler(ioa_engine_handle e, void *arg) {
UNUSED_ARG(e);
if(!arg) return;
if (!arg)
return;
rtcp_map* map=(rtcp_map*)arg;
rtcp_map *map = (rtcp_map *)arg;
if(rtcp_map_valid(map)) {
if (rtcp_map_valid(map)) {
TURN_MUTEX_LOCK(&map->mutex);
timeout_check_arg_type tcat;
tcat.tn=0;
tcat.t=turn_time();
tcat.tn = 0;
tcat.t = turn_time();
ur_map_foreach_arg(map->map, timeout_check, &tcat);
TURN_MUTEX_UNLOCK(&map->mutex);
int i=0;
for(i=0;i<tcat.tn;i++) {
rtcp_map_del(map,tcat.tokens[i]);
int i = 0;
for (i = 0; i < tcat.tn; i++) {
rtcp_map_del(map, tcat.tokens[i]);
}
}
}
static int rtcp_map_init(rtcp_map* map, ioa_engine_handle e) {
if (map) {
if (map->magic != MAGIC_RTCP_MAP) {
map->magic = MAGIC_RTCP_MAP;
map->map = ur_map_create();
if (e)
map->timer_ev = set_ioa_timer(e, 3, 0, rtcp_map_timeout_handler,
map, 1, "rtcp_map_timeout_handler");
TURN_MUTEX_INIT(&map->mutex);
if (rtcp_map_valid(map))
return 0;
}
}
return -1;
static int rtcp_map_init(rtcp_map *map, ioa_engine_handle e) {
if (map) {
if (map->magic != MAGIC_RTCP_MAP) {
map->magic = MAGIC_RTCP_MAP;
map->map = ur_map_create();
if (e)
map->timer_ev = set_ioa_timer(e, 3, 0, rtcp_map_timeout_handler, map, 1, "rtcp_map_timeout_handler");
TURN_MUTEX_INIT(&map->mutex);
if (rtcp_map_valid(map))
return 0;
}
}
return -1;
}
rtcp_map* rtcp_map_create(ioa_engine_handle e) {
rtcp_map *map=(rtcp_map*)calloc(sizeof(rtcp_map), 1);
if(rtcp_map_init(map,e)<0) {
rtcp_map *rtcp_map_create(ioa_engine_handle e) {
rtcp_map *map = (rtcp_map *)calloc(sizeof(rtcp_map), 1);
if (rtcp_map_init(map, e) < 0) {
free(map);
return NULL;
}
@ -189,20 +184,23 @@ rtcp_map* rtcp_map_create(ioa_engine_handle e) {
* 0 - success
* -1 - error
*/
int rtcp_map_put(rtcp_map* map, rtcp_token_type token, ioa_socket_handle s) {
if(!rtcp_map_valid(map)) return -1;
int rtcp_map_put(rtcp_map *map, rtcp_token_type token, ioa_socket_handle s) {
if (!rtcp_map_valid(map))
return -1;
else {
rtcp_alloc_type *value=(rtcp_alloc_type*)calloc(sizeof(rtcp_alloc_type), 1);
if(!value) return -1;
rtcp_alloc_type *value = (rtcp_alloc_type *)calloc(sizeof(rtcp_alloc_type), 1);
if (!value)
return -1;
value->s=s;
value->t=turn_time() + RTCP_TIMEOUT;
value->token=token;
value->s = s;
value->t = turn_time() + RTCP_TIMEOUT;
value->token = token;
TURN_MUTEX_LOCK(&map->mutex);
int ret = ur_map_put(map->map,token,(ur_map_value_type)value);
//TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"%s: 111.111: ret=%d, token=%llu\n",__FUNCTION__,ret,token);
int ret = ur_map_put(map->map, token, (ur_map_value_type)value);
// TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"%s: 111.111: ret=%d, token=%llu\n",__FUNCTION__,ret,token);
TURN_MUTEX_UNLOCK(&map->mutex);
if(ret<0) free(value);
if (ret < 0)
free(value);
return ret;
}
}
@ -212,40 +210,40 @@ int rtcp_map_put(rtcp_map* map, rtcp_token_type token, ioa_socket_handle s) {
* >=0 - success
* <0 - not found
*/
ioa_socket_handle rtcp_map_get(rtcp_map* map, rtcp_token_type token) {
ioa_socket_handle s = NULL;
if (rtcp_map_valid(map)) {
ur_map_value_type value;
TURN_MUTEX_LOCK(&map->mutex);
int ret = ur_map_get(map->map, token, &value);
if (ret) {
rtcp_alloc_type* rval = (rtcp_alloc_type*) value;
if (rval) {
s = rval->s;
rtcp_map_del_savefd(map, token);
}
}
TURN_MUTEX_UNLOCK(&map->mutex);
}
return s;
ioa_socket_handle rtcp_map_get(rtcp_map *map, rtcp_token_type token) {
ioa_socket_handle s = NULL;
if (rtcp_map_valid(map)) {
ur_map_value_type value;
TURN_MUTEX_LOCK(&map->mutex);
int ret = ur_map_get(map->map, token, &value);
if (ret) {
rtcp_alloc_type *rval = (rtcp_alloc_type *)value;
if (rval) {
s = rval->s;
rtcp_map_del_savefd(map, token);
}
}
TURN_MUTEX_UNLOCK(&map->mutex);
}
return s;
}
void rtcp_map_free(rtcp_map** map) {
if(map && rtcp_map_valid(*map)) {
void rtcp_map_free(rtcp_map **map) {
if (map && rtcp_map_valid(*map)) {
TURN_MUTEX_LOCK(&((*map)->mutex));
IOA_EVENT_DEL((*map)->timer_ev);
ur_map_foreach((*map)->map, foreachcb_free);
ur_map_free(&((*map)->map));
(*map)->magic=0;
(*map)->magic = 0;
TURN_MUTEX_UNLOCK(&((*map)->mutex));
TURN_MUTEX_DESTROY(&((*map)->mutex));
free(*map);
*map=NULL;
*map = NULL;
}
}
size_t rtcp_map_size(const rtcp_map* map) {
if(rtcp_map_valid(map)) {
size_t rtcp_map_size(const rtcp_map *map) {
if (rtcp_map_valid(map)) {
TURN_MUTEX_LOCK(&map->mutex);
size_t ret = ur_map_size(map->map);
TURN_MUTEX_UNLOCK(&map->mutex);

View File

@ -31,8 +31,8 @@
#ifndef __TURN_RTCP_MAP__
#define __TURN_RTCP_MAP__
#include "ns_turn_maps.h"
#include "ns_turn_ioalib.h"
#include "ns_turn_maps.h"
#ifdef __cplusplus
extern "C" {
@ -47,30 +47,30 @@ typedef struct _rtcp_map rtcp_map;
////////////////////////////////////////////////
rtcp_map* rtcp_map_create(ioa_engine_handle e);
rtcp_map *rtcp_map_create(ioa_engine_handle e);
/**
* @ret:
* 0 - success
* -1 - error
*/
int rtcp_map_put(rtcp_map* map, rtcp_token_type key, ioa_socket_handle s);
int rtcp_map_put(rtcp_map *map, rtcp_token_type key, ioa_socket_handle s);
/**
* @ret:
* >=0 - success
* <0 - not found
*/
ioa_socket_handle rtcp_map_get(rtcp_map* map, rtcp_token_type token);
ioa_socket_handle rtcp_map_get(rtcp_map *map, rtcp_token_type token);
/**
* @ret:
* 1 - success
* 0 - not found
*/
void rtcp_map_free(rtcp_map** map);
void rtcp_map_free(rtcp_map **map);
size_t rtcp_map_size(const rtcp_map* map);
size_t rtcp_map_size(const rtcp_map *map);
////////////////////////////////////////////

File diff suppressed because it is too large Load Diff

View File

@ -31,8 +31,8 @@
#ifndef __TURN_SERVER__
#define __TURN_SERVER__
#include "ns_turn_utils.h"
#include "ns_turn_session.h"
#include "ns_turn_utils.h"
#ifdef __cplusplus
extern "C" {
@ -45,9 +45,9 @@ extern "C" {
//////////// ALTERNATE-SERVER /////////////
struct _turn_server_addrs_list {
ioa_addr *addrs;
volatile size_t size;
TURN_MUTEX_DECLARE(m)
ioa_addr *addrs;
volatile size_t size;
TURN_MUTEX_DECLARE(m)
};
typedef struct _turn_server_addrs_list turn_server_addrs_list_t;
@ -57,7 +57,8 @@ void init_turn_server_addrs_list(turn_server_addrs_list_t *l);
////////// RFC 5780 ///////////////////////
typedef int (*get_alt_addr_cb)(ioa_addr *addr, ioa_addr *alt_addr);
typedef int (*send_message_cb)(ioa_engine_handle e, ioa_network_buffer_handle nbh, ioa_addr *origin, ioa_addr *destination);
typedef int (*send_message_cb)(ioa_engine_handle e, ioa_network_buffer_handle nbh, ioa_addr *origin,
ioa_addr *destination);
//////////////////////////////////////////
@ -66,43 +67,43 @@ extern int TURN_MAX_ALLOCATE_TIMEOUT_STUN_ONLY;
typedef uint8_t turnserver_id;
enum _MESSAGE_TO_RELAY_TYPE {
RMT_UNKNOWN = 0,
RMT_SOCKET,
RMT_CB_SOCKET,
RMT_MOBILE_SOCKET,
RMT_CANCEL_SESSION
};
enum _MESSAGE_TO_RELAY_TYPE { RMT_UNKNOWN = 0, RMT_SOCKET, RMT_CB_SOCKET, RMT_MOBILE_SOCKET, RMT_CANCEL_SESSION };
typedef enum _MESSAGE_TO_RELAY_TYPE MESSAGE_TO_RELAY_TYPE;
///////// ALLOCATION DEFAULT ADDRESS FAMILY TYPES /////////////////////
enum _ALLOCATION_DEFAULT_ADDRESS_FAMILY {
ALLOCATION_DEFAULT_ADDRESS_FAMILY_IPV4 = 0,
ALLOCATION_DEFAULT_ADDRESS_FAMILY_IPV6,
ALLOCATION_DEFAULT_ADDRESS_FAMILY_KEEP,
ALLOCATION_DEFAULT_ADDRESS_FAMILY_IPV4 = 0,
ALLOCATION_DEFAULT_ADDRESS_FAMILY_IPV6,
ALLOCATION_DEFAULT_ADDRESS_FAMILY_KEEP,
};
typedef enum _ALLOCATION_DEFAULT_ADDRESS_FAMILY ALLOCATION_DEFAULT_ADDRESS_FAMILY;
struct socket_message {
ioa_socket_handle s;
ioa_net_data nd;
int can_resume;
ioa_socket_handle s;
ioa_net_data nd;
int can_resume;
};
typedef enum {
DONT_FRAGMENT_UNSUPPORTED=0,
DONT_FRAGMENT_SUPPORTED,
DONT_FRAGMENT_SUPPORT_EMULATED
DONT_FRAGMENT_UNSUPPORTED = 0,
DONT_FRAGMENT_SUPPORTED,
DONT_FRAGMENT_SUPPORT_EMULATED
} dont_fragment_option_t;
struct _turn_turnserver;
typedef struct _turn_turnserver turn_turnserver;
typedef void (*get_username_resume_cb)(int success, int oauth, int max_session_time, hmackey_t hmackey, password_t pwd, turn_turnserver *server, uint64_t ctxkey, ioa_net_data *in_buffer, uint8_t* realm);
typedef uint8_t *(*get_user_key_cb)(turnserver_id id, turn_credential_type ct, int in_oauth, int *out_oauth, uint8_t *uname, uint8_t *realm, get_username_resume_cb resume, ioa_net_data *in_buffer, uint64_t ctxkey, int *postpone_reply);
typedef void (*get_username_resume_cb)(int success, int oauth, int max_session_time, hmackey_t hmackey, password_t pwd,
turn_turnserver *server, uint64_t ctxkey, ioa_net_data *in_buffer,
uint8_t *realm);
typedef uint8_t *(*get_user_key_cb)(turnserver_id id, turn_credential_type ct, int in_oauth, int *out_oauth,
uint8_t *uname, uint8_t *realm, get_username_resume_cb resume,
ioa_net_data *in_buffer, uint64_t ctxkey, int *postpone_reply);
typedef int (*check_new_allocation_quota_cb)(uint8_t *username, int oauth, uint8_t *realm);
typedef void (*release_allocation_quota_cb)(uint8_t *username, int oauth, uint8_t *realm);
typedef int (*send_socket_to_relay_cb)(turnserver_id id, uint64_t cid, stun_tid *tid, ioa_socket_handle s, int message_integrity, MESSAGE_TO_RELAY_TYPE rmt, ioa_net_data *nd, int can_resume);
typedef int (*send_socket_to_relay_cb)(turnserver_id id, uint64_t cid, stun_tid *tid, ioa_socket_handle s,
int message_integrity, MESSAGE_TO_RELAY_TYPE rmt, ioa_net_data *nd,
int can_resume);
typedef int (*send_turn_session_info_cb)(struct turn_session_info *tsi);
typedef void (*send_https_socket_cb)(ioa_socket_handle s);
@ -110,140 +111,111 @@ typedef band_limit_t (*allocate_bps_cb)(band_limit_t bps, int positive);
struct _turn_turnserver {
turnserver_id id;
turnserver_id id;
turnsession_id session_id_counter;
ur_map *sessions_map;
turnsession_id session_id_counter;
ur_map *sessions_map;
turn_time_t ctime;
turn_time_t ctime;
ioa_engine_handle e;
int verbose;
int fingerprint;
int rfc5780;
vintp check_origin;
vintp stale_nonce;
vintp max_allocate_lifetime;
vintp channel_lifetime;
vintp permission_lifetime;
vintp stun_only;
vintp no_stun;
vintp no_software_attribute;
vintp web_admin_listen_on_workers;
vintp secure_stun;
turn_credential_type ct;
get_alt_addr_cb alt_addr_cb;
send_message_cb sm_cb;
dont_fragment_option_t dont_fragment;
int (*disconnect)(ts_ur_super_session*);
get_user_key_cb userkeycb;
check_new_allocation_quota_cb chquotacb;
release_allocation_quota_cb raqcb;
int external_ip_set;
ioa_addr external_ip;
vintp allow_loopback_peers;
vintp no_multicast_peers;
send_turn_session_info_cb send_turn_session_info;
send_https_socket_cb send_https_socket;
ioa_engine_handle e;
int verbose;
int fingerprint;
int rfc5780;
vintp check_origin;
vintp stale_nonce;
vintp max_allocate_lifetime;
vintp channel_lifetime;
vintp permission_lifetime;
vintp stun_only;
vintp no_stun;
vintp no_software_attribute;
vintp web_admin_listen_on_workers;
vintp secure_stun;
turn_credential_type ct;
get_alt_addr_cb alt_addr_cb;
send_message_cb sm_cb;
dont_fragment_option_t dont_fragment;
int (*disconnect)(ts_ur_super_session *);
get_user_key_cb userkeycb;
check_new_allocation_quota_cb chquotacb;
release_allocation_quota_cb raqcb;
int external_ip_set;
ioa_addr external_ip;
vintp allow_loopback_peers;
vintp no_multicast_peers;
send_turn_session_info_cb send_turn_session_info;
send_https_socket_cb send_https_socket;
/* RFC 6062 ==>> */
vintp no_udp_relay;
vintp no_tcp_relay;
ur_map *tcp_relay_connections;
send_socket_to_relay_cb send_socket_to_relay;
/* <<== RFC 6062 */
/* RFC 6062 ==>> */
vintp no_udp_relay;
vintp no_tcp_relay;
ur_map *tcp_relay_connections;
send_socket_to_relay_cb send_socket_to_relay;
/* <<== RFC 6062 */
/* Alternate servers ==>> */
turn_server_addrs_list_t *alternate_servers_list;
size_t as_counter;
turn_server_addrs_list_t *tls_alternate_servers_list;
size_t tls_as_counter;
turn_server_addrs_list_t *aux_servers_list;
int self_udp_balance;
/* Alternate servers ==>> */
turn_server_addrs_list_t *alternate_servers_list;
size_t as_counter;
turn_server_addrs_list_t *tls_alternate_servers_list;
size_t tls_as_counter;
turn_server_addrs_list_t *aux_servers_list;
int self_udp_balance;
/* White/black listing of address ranges */
ip_range_list_t* ip_whitelist;
ip_range_list_t* ip_blacklist;
/* White/black listing of address ranges */
ip_range_list_t *ip_whitelist;
ip_range_list_t *ip_blacklist;
/* Mobility */
vintp mobility;
ur_map *mobile_connections_map;
/* Mobility */
vintp mobility;
ur_map *mobile_connections_map;
/* Server relay */
int server_relay;
/* Server relay */
int server_relay;
/* Bandwidth draft: */
allocate_bps_cb allocate_bps_func;
/* Bandwidth draft: */
allocate_bps_cb allocate_bps_func;
/* oAuth: */
int oauth;
const char* oauth_server_name;
/* oAuth: */
int oauth;
const char *oauth_server_name;
/* ACME redirect URL */
const char* acme_redirect;
/* ACME redirect URL */
const char *acme_redirect;
/* Allocation Default Address Family */
ALLOCATION_DEFAULT_ADDRESS_FAMILY allocation_default_address_family;
/* Allocation Default Address Family */
ALLOCATION_DEFAULT_ADDRESS_FAMILY allocation_default_address_family;
/* Log Binding Requrest */
vintp log_binding;
/* Log Binding Requrest */
vintp log_binding;
/* Disable handling old STUN Binding Requests and disable MAPPED-ADDRESS attribute in response */
vintp no_stun_backward_compatibility;
/* Disable handling old STUN Binding Requests and disable MAPPED-ADDRESS attribute in response */
vintp no_stun_backward_compatibility;
/* Only send RESPONSE-ORIGIN attribute in response if RFC5780 is enabled */
vintp response_origin_only_with_rfc5780;
/* Only send RESPONSE-ORIGIN attribute in response if RFC5780 is enabled */
vintp response_origin_only_with_rfc5780;
};
const char * get_version(turn_turnserver *server);
const char *get_version(turn_turnserver *server);
///////////////////////////////////////////
void init_turn_server(turn_turnserver* server,
turnserver_id id, int verbose,
ioa_engine_handle e,
turn_credential_type ct,
int stun_port,
int fingerprint,
dont_fragment_option_t dont_fragment,
get_user_key_cb userkeycb,
check_new_allocation_quota_cb chquotacb,
release_allocation_quota_cb raqcb,
ioa_addr *external_addr,
vintp check_origin,
vintp no_tcp_relay,
vintp no_udp_relay,
vintp stale_nonce,
vintp max_allocate_lifetime,
vintp channel_lifetime,
vintp permission_lifetime,
vintp stun_only,
vintp no_stun,
vintp no_software_attribute,
vintp web_admin_listen_on_workers,
turn_server_addrs_list_t *alternate_servers_list,
turn_server_addrs_list_t *tls_alternate_servers_list,
turn_server_addrs_list_t *aux_servers_list,
int self_udp_balance,
vintp no_multicast_peers,
vintp allow_loopback_peers,
ip_range_list_t* ip_whitelist,
ip_range_list_t* ip_blacklist,
send_socket_to_relay_cb send_socket_to_relay,
vintp secure_stun,
vintp mobility,
int server_relay,
send_turn_session_info_cb send_turn_session_info,
send_https_socket_cb send_https_socket,
allocate_bps_cb allocate_bps_func,
int oauth,
const char* oauth_server_name,
const char* acme_redirect,
ALLOCATION_DEFAULT_ADDRESS_FAMILY allocation_default_address_family,
vintp log_binding,
vintp no_stun_backward_compatibility,
vintp response_origin_only_with_rfc5780
);
void init_turn_server(turn_turnserver *server, turnserver_id id, int verbose, ioa_engine_handle e,
turn_credential_type ct, int stun_port, int fingerprint, dont_fragment_option_t dont_fragment,
get_user_key_cb userkeycb, check_new_allocation_quota_cb chquotacb,
release_allocation_quota_cb raqcb, ioa_addr *external_addr, vintp check_origin,
vintp no_tcp_relay, vintp no_udp_relay, vintp stale_nonce, vintp max_allocate_lifetime,
vintp channel_lifetime, vintp permission_lifetime, vintp stun_only, vintp no_stun,
vintp no_software_attribute, vintp web_admin_listen_on_workers,
turn_server_addrs_list_t *alternate_servers_list,
turn_server_addrs_list_t *tls_alternate_servers_list, turn_server_addrs_list_t *aux_servers_list,
int self_udp_balance, vintp no_multicast_peers, vintp allow_loopback_peers,
ip_range_list_t *ip_whitelist, ip_range_list_t *ip_blacklist,
send_socket_to_relay_cb send_socket_to_relay, vintp secure_stun, vintp mobility, int server_relay,
send_turn_session_info_cb send_turn_session_info, send_https_socket_cb send_https_socket,
allocate_bps_cb allocate_bps_func, int oauth, const char *oauth_server_name,
const char *acme_redirect, ALLOCATION_DEFAULT_ADDRESS_FAMILY allocation_default_address_family,
vintp log_binding, vintp no_stun_backward_compatibility, vintp response_origin_only_with_rfc5780);
ioa_engine_handle turn_server_get_engine(turn_turnserver *s);
@ -253,11 +225,13 @@ void set_rfc5780(turn_turnserver *server, get_alt_addr_cb cb, send_message_cb sm
///////////////////////////////////////////
int open_client_connection_session(turn_turnserver* server, struct socket_message *sm);
int shutdown_client_connection(turn_turnserver *server, ts_ur_super_session *ss, int force, const char* reason);
void set_disconnect_cb(turn_turnserver* server, int (*disconnect)(ts_ur_super_session*));
int open_client_connection_session(turn_turnserver *server, struct socket_message *sm);
int shutdown_client_connection(turn_turnserver *server, ts_ur_super_session *ss, int force, const char *reason);
void set_disconnect_cb(turn_turnserver *server, int (*disconnect)(ts_ur_super_session *));
int turnserver_accept_tcp_client_data_connection(turn_turnserver *server, tcp_connection_id tcid, stun_tid *tid, ioa_socket_handle s, int message_integrity, ioa_net_data *nd, int can_resume);
int turnserver_accept_tcp_client_data_connection(turn_turnserver *server, tcp_connection_id tcid, stun_tid *tid,
ioa_socket_handle s, int message_integrity, ioa_net_data *nd,
int can_resume);
int report_turn_session_info(turn_turnserver *server, ts_ur_super_session *ss, int force_invalid);

View File

@ -31,10 +31,10 @@
#ifndef __TURN_SESSION__
#define __TURN_SESSION__
#include "ns_turn_utils.h"
#include "ns_turn_maps.h"
#include "ns_turn_ioalib.h"
#include "ns_turn_allocation.h"
#include "ns_turn_ioalib.h"
#include "ns_turn_maps.h"
#include "ns_turn_utils.h"
#ifdef __cplusplus
extern "C" {
@ -44,29 +44,29 @@ extern "C" {
typedef struct _perf_options_t {
volatile band_limit_t max_bps;
vint total_quota;
vint user_quota;
volatile band_limit_t max_bps;
vint total_quota;
vint user_quota;
} perf_options_t;
struct _realm_options_t {
char name[STUN_MAX_REALM_SIZE + 1];
char name[STUN_MAX_REALM_SIZE + 1];
perf_options_t perf_options;
perf_options_t perf_options;
};
//////////////// session info //////////////////////
typedef uint64_t turnsession_id;
#define NONCE_MAX_SIZE (NONCE_LENGTH_32BITS*4+1)
#define NONCE_MAX_SIZE (NONCE_LENGTH_32BITS * 4 + 1)
typedef uint64_t mobile_id_t;
struct _ts_ur_super_session {
void* server;
void *server;
turnsession_id id;
turn_time_t start_time;
ioa_socket_handle client_socket;
@ -78,7 +78,7 @@ struct _ts_ur_super_session {
/* Auth */
uint8_t nonce[NONCE_MAX_SIZE];
turn_time_t nonce_expiration_time;
uint8_t username[STUN_MAX_USERNAME_SIZE+1];
uint8_t username[STUN_MAX_USERNAME_SIZE + 1];
hmackey_t hmackey;
int hmackey_set;
password_t pwd;
@ -127,63 +127,63 @@ struct _ts_ur_super_session {
#define TURN_MAIN_PEERS_ARRAY_SIZE (5)
typedef struct _addr_data {
ioa_addr addr;
char saddr[TURN_ADDR_STR_SIZE];
ioa_addr addr;
char saddr[TURN_ADDR_STR_SIZE];
} addr_data;
struct turn_session_info {
turnsession_id id;
int valid;
turn_time_t start_time;
turn_time_t expiration_time;
SOCKET_TYPE client_protocol;
SOCKET_TYPE peer_protocol;
char tls_method[17];
char tls_cipher[65];
addr_data local_addr_data;
addr_data remote_addr_data;
addr_data relay_addr_data_ipv4;
addr_data relay_addr_data_ipv6;
uint8_t username[STUN_MAX_USERNAME_SIZE+1];
int enforce_fingerprints;
/* Stats */
uint64_t received_packets;
uint64_t sent_packets;
uint64_t received_bytes;
uint64_t sent_bytes;
uint32_t received_rate;
uint32_t sent_rate;
uint32_t total_rate;
uint64_t peer_received_packets;
uint64_t peer_sent_packets;
uint64_t peer_received_bytes;
uint64_t peer_sent_bytes;
uint32_t peer_received_rate;
uint32_t peer_sent_rate;
uint32_t peer_total_rate;
/* Mobile */
int is_mobile;
/* Peers */
addr_data main_peers_data[TURN_MAIN_PEERS_ARRAY_SIZE];
size_t main_peers_size;
addr_data *extra_peers_data;
size_t extra_peers_size;
/* Realm */
char realm[STUN_MAX_REALM_SIZE + 1];
char origin[STUN_MAX_ORIGIN_SIZE + 1];
/* Bandwidth */
band_limit_t bps;
turnsession_id id;
int valid;
turn_time_t start_time;
turn_time_t expiration_time;
SOCKET_TYPE client_protocol;
SOCKET_TYPE peer_protocol;
char tls_method[17];
char tls_cipher[65];
addr_data local_addr_data;
addr_data remote_addr_data;
addr_data relay_addr_data_ipv4;
addr_data relay_addr_data_ipv6;
uint8_t username[STUN_MAX_USERNAME_SIZE + 1];
int enforce_fingerprints;
/* Stats */
uint64_t received_packets;
uint64_t sent_packets;
uint64_t received_bytes;
uint64_t sent_bytes;
uint32_t received_rate;
uint32_t sent_rate;
uint32_t total_rate;
uint64_t peer_received_packets;
uint64_t peer_sent_packets;
uint64_t peer_received_bytes;
uint64_t peer_sent_bytes;
uint32_t peer_received_rate;
uint32_t peer_sent_rate;
uint32_t peer_total_rate;
/* Mobile */
int is_mobile;
/* Peers */
addr_data main_peers_data[TURN_MAIN_PEERS_ARRAY_SIZE];
size_t main_peers_size;
addr_data *extra_peers_data;
size_t extra_peers_size;
/* Realm */
char realm[STUN_MAX_REALM_SIZE + 1];
char origin[STUN_MAX_ORIGIN_SIZE + 1];
/* Bandwidth */
band_limit_t bps;
};
void turn_session_info_init(struct turn_session_info* tsi);
void turn_session_info_clean(struct turn_session_info* tsi);
void turn_session_info_add_peer(struct turn_session_info* tsi, ioa_addr *peer);
void turn_session_info_init(struct turn_session_info *tsi);
void turn_session_info_clean(struct turn_session_info *tsi);
void turn_session_info_add_peer(struct turn_session_info *tsi, ioa_addr *peer);
int turn_session_info_copy_from(struct turn_session_info* tsi, ts_ur_super_session *ss);
int turn_session_info_copy_from(struct turn_session_info *tsi, ts_ur_super_session *ss);
////////////// ss /////////////////////
allocation* get_allocation_ss(ts_ur_super_session *ss);
allocation *get_allocation_ss(ts_ur_super_session *ss);
///////////////////////////////////////////////////////