?? stun_msg.c
字號(hào):
/* $Id: stun_msg.c 1289 2007-05-22 21:55:31Z bennylp $ */
/*
* Copyright (C) 2003-2005 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <pjnath/stun_msg.h>
#include <pjnath/errno.h>
#include <pjlib-util/crc32.h>
#include <pjlib-util/hmac_sha1.h>
#include <pjlib-util/md5.h>
#include <pj/assert.h>
#include <pj/log.h>
#include <pj/os.h>
#include <pj/pool.h>
#include <pj/rand.h>
#include <pj/string.h>
#define THIS_FILE "stun_msg.c"
#define STUN_XOR_FINGERPRINT 0x5354554eL
static const char *stun_method_names[] =
{
"Unknown", /* 0 */
"Binding", /* 1 */
"Shared Secret", /* 2 */
"Allocate", /* 3 */
"Send", /* 4 */
"Data", /* 5 */
"Set Active Destination", /* 6 */
"Connect", /* 7 */
"Connect Status" /* 8 */
};
static struct
{
int err_code;
const char *err_msg;
} stun_err_msg_map[] =
{
{ PJ_STUN_SC_TRY_ALTERNATE, "Try Alternate"},
{ PJ_STUN_SC_BAD_REQUEST, "Bad Request"},
{ PJ_STUN_SC_UNAUTHORIZED, "Unauthorized"},
{ PJ_STUN_SC_UNKNOWN_ATTRIBUTE, "Unknown Attribute"},
{ PJ_STUN_SC_STALE_CREDENTIALS, "Stale Credentials"},
{ PJ_STUN_SC_INTEGRITY_CHECK_FAILURE, "Integrity Check Failure"},
{ PJ_STUN_SC_MISSING_USERNAME, "Missing Username"},
{ PJ_STUN_SC_USE_TLS, "Use TLS"},
{ PJ_STUN_SC_MISSING_REALM, "Missing Realm"},
{ PJ_STUN_SC_MISSING_NONCE, "Missing Nonce"},
{ PJ_STUN_SC_UNKNOWN_USERNAME, "Unknown Username"},
{ PJ_STUN_SC_NO_BINDING, "No Binding"},
{ PJ_STUN_SC_STALE_NONCE, "Stale Nonce"},
{ PJ_STUN_SC_TRANSITIONING, "Active Destination Already Set"},
{ PJ_STUN_SC_UNSUPP_TRANSPORT_PROTO, "Unsupported Transport Protocol"},
{ PJ_STUN_SC_INVALID_IP_ADDR, "Invalid IP Address"},
{ PJ_STUN_SC_INVALID_PORT, "Invalid Port"},
{ PJ_STUN_SC_OPER_TCP_ONLY, "Operation for TCP Only"},
{ PJ_STUN_SC_CONNECTION_FAILURE, "Connection Failure"},
{ PJ_STUN_SC_CONNECTION_TIMEOUT, "Connection Timeout"},
{ PJ_STUN_SC_ALLOCATION_QUOTA_REACHED, "Allocation Quota Reached"},
{ PJ_STUN_SC_ROLE_CONFLICT, "Role Conflict"},
{ PJ_STUN_SC_SERVER_ERROR, "Server Error"},
{ PJ_STUN_SC_INSUFFICIENT_CAPACITY, "Insufficient Capacity"},
{ PJ_STUN_SC_GLOBAL_FAILURE, "Global Failure"}
};
struct attr_desc
{
const char *name;
pj_status_t (*decode_attr)(pj_pool_t *pool, const pj_uint8_t *buf,
void **p_attr);
pj_status_t (*encode_attr)(const void *a, pj_uint8_t *buf,
unsigned len, unsigned *printed);
};
static pj_status_t decode_sockaddr_attr(pj_pool_t *pool,
const pj_uint8_t *buf,
void **p_attr);
static pj_status_t decode_xored_sockaddr_attr(pj_pool_t *pool,
const pj_uint8_t *buf,
void **p_attr);
static pj_status_t encode_sockaddr_attr(const void *a, pj_uint8_t *buf,
unsigned len,
unsigned *printed);
static pj_status_t decode_string_attr(pj_pool_t *pool,
const pj_uint8_t *buf,
void **p_attr);
static pj_status_t encode_string_attr(const void *a, pj_uint8_t *buf,
unsigned len, unsigned *printed);
static pj_status_t decode_msgint_attr(pj_pool_t *pool,
const pj_uint8_t *buf,
void **p_attr);
static pj_status_t encode_msgint_attr(const void *a, pj_uint8_t *buf,
unsigned len, unsigned *printed);
static pj_status_t decode_errcode_attr(pj_pool_t *pool,
const pj_uint8_t *buf,
void **p_attr);
static pj_status_t encode_errcode_attr(const void *a, pj_uint8_t *buf,
unsigned len, unsigned *printed);
static pj_status_t decode_unknown_attr(pj_pool_t *pool,
const pj_uint8_t *buf,
void **p_attr);
static pj_status_t encode_unknown_attr(const void *a, pj_uint8_t *buf,
unsigned len, unsigned *printed);
static pj_status_t decode_uint_attr(pj_pool_t *pool,
const pj_uint8_t *buf,
void **p_attr);
static pj_status_t encode_uint_attr(const void *a, pj_uint8_t *buf,
unsigned len, unsigned *printed);
static pj_status_t decode_uint64_attr(pj_pool_t *pool,
const pj_uint8_t *buf,
void **p_attr);
static pj_status_t encode_uint64_attr(const void *a, pj_uint8_t *buf,
unsigned len, unsigned *printed);
static pj_status_t decode_binary_attr(pj_pool_t *pool,
const pj_uint8_t *buf,
void **p_attr);
static pj_status_t encode_binary_attr(const void *a, pj_uint8_t *buf,
unsigned len, unsigned *printed);
static pj_status_t decode_empty_attr(pj_pool_t *pool,
const pj_uint8_t *buf,
void **p_attr);
static pj_status_t encode_empty_attr(const void *a, pj_uint8_t *buf,
unsigned len, unsigned *printed);
static struct attr_desc mandatory_attr_desc[] =
{
{
/* type zero */
NULL,
NULL,
NULL
},
{
/* PJ_STUN_ATTR_MAPPED_ADDR, */
"MAPPED-ADDRESS",
&decode_sockaddr_attr,
&encode_sockaddr_attr
},
{
/* PJ_STUN_ATTR_RESPONSE_ADDR, */
"RESPONSE-ADDRESS",
&decode_sockaddr_attr,
&encode_sockaddr_attr
},
{
/* PJ_STUN_ATTR_CHANGE_REQUEST, */
"CHANGE-REQUEST",
&decode_uint_attr,
&encode_uint_attr
},
{
/* PJ_STUN_ATTR_SOURCE_ADDR, */
"SOURCE-ADDRESS",
&decode_sockaddr_attr,
&encode_sockaddr_attr
},
{
/* PJ_STUN_ATTR_CHANGED_ADDR, */
"CHANGED-ADDRESS",
&decode_sockaddr_attr,
&encode_sockaddr_attr
},
{
/* PJ_STUN_ATTR_USERNAME, */
"USERNAME",
&decode_string_attr,
&encode_string_attr
},
{
/* PJ_STUN_ATTR_PASSWORD, */
"PASSWORD",
&decode_string_attr,
&encode_string_attr
},
{
/* PJ_STUN_ATTR_MESSAGE_INTEGRITY, */
"MESSAGE-INTEGRITY",
&decode_msgint_attr,
&encode_msgint_attr
},
{
/* PJ_STUN_ATTR_ERROR_CODE, */
"ERROR-CODE",
&decode_errcode_attr,
&encode_errcode_attr
},
{
/* PJ_STUN_ATTR_UNKNOWN_ATTRIBUTES, */
"UNKNOWN-ATTRIBUTES",
&decode_unknown_attr,
&encode_unknown_attr
},
{
/* PJ_STUN_ATTR_REFLECTED_FROM, */
"REFLECTED-FROM",
&decode_sockaddr_attr,
&encode_sockaddr_attr
},
{
/* ID 0x000C is not assigned */
NULL,
NULL,
NULL
},
{
/* PJ_STUN_ATTR_LIFETIME, */
"LIFETIME",
&decode_uint_attr,
&encode_uint_attr
},
{
/* ID 0x000E is not assigned */
NULL,
NULL,
NULL
},
{
/* PJ_STUN_ATTR_MAGIC_COOKIE */
"MAGIC-COOKIE",
&decode_uint_attr,
&encode_uint_attr
},
{
/* PJ_STUN_ATTR_BANDWIDTH, */
"BANDWIDTH",
&decode_uint_attr,
&encode_uint_attr
},
{
/* ID 0x0011 is not assigned */
NULL,
NULL,
NULL
},
{
/* PJ_STUN_ATTR_REMOTE_ADDRESS, */
"REMOTE-ADDRESS",
&decode_sockaddr_attr,
&encode_sockaddr_attr
},
{
/* PJ_STUN_ATTR_DATA, */
"DATA",
&decode_binary_attr,
&encode_binary_attr
},
{
/* PJ_STUN_ATTR_REALM, */
"REALM",
&decode_string_attr,
&encode_string_attr
},
{
/* PJ_STUN_ATTR_NONCE, */
"NONCE",
&decode_string_attr,
&encode_string_attr
},
{
/* PJ_STUN_ATTR_RELAY_ADDRESS, */
"RELAY-ADDRESS",
&decode_sockaddr_attr,
&encode_sockaddr_attr
},
{
/* PJ_STUN_ATTR_REQUESTED_ADDR_TYPE, */
"REQUESTED-ADDRESS-TYPE",
&decode_uint_attr,
&encode_uint_attr
},
{
/* PJ_STUN_ATTR_REQUESTED_PORT_PROPS, */
"REQUESTED-PORT-PROPS",
&decode_uint_attr,
&encode_uint_attr
},
{
/* PJ_STUN_ATTR_REQUESTED_TRANSPORT, */
"REQUESTED-TRANSPORT",
&decode_uint_attr,
&encode_uint_attr
},
{
/* ID 0x001A is not assigned */
NULL,
NULL,
NULL
},
{
/* ID 0x001B is not assigned */
NULL,
NULL,
NULL
},
{
/* ID 0x001C is not assigned */
NULL,
NULL,
NULL
},
{
/* ID 0x001D is not assigned */
NULL,
NULL,
NULL
},
{
/* ID 0x001E is not assigned */
NULL,
NULL,
NULL
},
{
/* ID 0x001F is not assigned */
NULL,
NULL,
NULL
},
{
/* PJ_STUN_ATTR_XOR_MAPPED_ADDRESS, */
"XOR-MAPPED-ADDRESS",
&decode_xored_sockaddr_attr,
&encode_sockaddr_attr
},
{
/* PJ_STUN_ATTR_TIMER_VAL, */
"TIMER-VAL",
&decode_uint_attr,
&encode_uint_attr
},
{
/* PJ_STUN_ATTR_REQUESTED_IP, */
"REQUESTED-IP",
&decode_sockaddr_attr,
&encode_sockaddr_attr
},
{
/* PJ_STUN_ATTR_XOR_REFLECTED_FROM, */
"XOR-REFLECTED-FROM",
&decode_xored_sockaddr_attr,
&encode_sockaddr_attr
},
{
/* PJ_STUN_ATTR_PRIORITY, */
"PRIORITY",
&decode_uint_attr,
&encode_uint_attr
},
{
/* PJ_STUN_ATTR_USE_CANDIDATE, */
"USE-CANDIDATE",
&decode_empty_attr,
&encode_empty_attr
},
{
/* PJ_STUN_ATTR_XOR_INTERNAL_ADDR, */
"XOR-INTERNAL-ADDRESS",
&decode_xored_sockaddr_attr,
&encode_sockaddr_attr
},
/* Sentinel */
{
/* PJ_STUN_ATTR_END_MANDATORY_ATTR */
NULL,
NULL,
NULL
}
};
static struct attr_desc extended_attr_desc[] =
{
{
/* ID 0x8021 is not assigned */
NULL,
NULL,
NULL
},
{
/* PJ_STUN_ATTR_SERVER, */
"SERVER",
&decode_string_attr,
&encode_string_attr
},
{
/* PJ_STUN_ATTR_ALTERNATE_SERVER, */
"ALTERNATE-SERVER",
&decode_sockaddr_attr,
&encode_sockaddr_attr
},
{
/* PJ_STUN_ATTR_REFRESH_INTERVAL, */
"REFRESH-INTERVAL",
&decode_uint_attr,
&encode_uint_attr
},
{
/* ID 0x8025 is not assigned*/
NULL,
NULL,
NULL
},
{
/* PADDING, 0x8026 */
NULL,
NULL,
NULL
},
{
/* CACHE-TIMEOUT, 0x8027 */
NULL,
NULL,
NULL
},
{
/* PJ_STUN_ATTR_FINGERPRINT, */
"FINGERPRINT",
&decode_uint_attr,
&encode_uint_attr
},
{
/* PJ_STUN_ATTR_ICE_CONTROLLED, */
"ICE-CONTROLLED",
&decode_uint64_attr,
&encode_uint64_attr
},
{
/* PJ_STUN_ATTR_ICE_CONTROLLING, */
"ICE-CONTROLLING",
&decode_uint64_attr,
&encode_uint64_attr
}
};
/*
* Get STUN message type name.
*/
PJ_DEF(const char*) pj_stun_get_method_name(unsigned msg_type)
{
unsigned method = PJ_STUN_GET_METHOD(msg_type);
if (method >= PJ_ARRAY_SIZE(stun_method_names))
return "???";
return stun_method_names[method];
}
/*
* Get STUN message class name.
*/
PJ_DEF(const char*) pj_stun_get_class_name(unsigned msg_type)
{
if (PJ_STUN_IS_REQUEST(msg_type))
return "request";
else if (PJ_STUN_IS_SUCCESS_RESPONSE(msg_type))
return "success response";
else if (PJ_STUN_IS_ERROR_RESPONSE(msg_type))
return "error response";
else if (PJ_STUN_IS_INDICATION(msg_type))
return "indication";
else
return "???";
}
static const struct attr_desc *find_attr_desc(unsigned attr_type)
{
struct attr_desc *desc;
/* Check that attr_desc array is valid */
pj_assert(PJ_ARRAY_SIZE(mandatory_attr_desc)==
PJ_STUN_ATTR_END_MANDATORY_ATTR+1);
pj_assert(mandatory_attr_desc[PJ_STUN_ATTR_END_MANDATORY_ATTR].decode_attr
== NULL);
pj_assert(mandatory_attr_desc[PJ_STUN_ATTR_USE_CANDIDATE].decode_attr
== &decode_empty_attr);
pj_assert(PJ_ARRAY_SIZE(extended_attr_desc) ==
PJ_STUN_ATTR_END_EXTENDED_ATTR-PJ_STUN_ATTR_START_EXTENDED_ATTR);
if (attr_type < PJ_STUN_ATTR_END_MANDATORY_ATTR)
desc = &mandatory_attr_desc[attr_type];
else if (attr_type >= PJ_STUN_ATTR_START_EXTENDED_ATTR &&
attr_type < PJ_STUN_ATTR_END_EXTENDED_ATTR)
desc = &extended_attr_desc[attr_type-PJ_STUN_ATTR_START_EXTENDED_ATTR];
else
return NULL;
return desc->decode_attr == NULL ? NULL : desc;
}
/*
* Get STUN attribute name.
*/
PJ_DEF(const char*) pj_stun_get_attr_name(unsigned attr_type)
{
const struct attr_desc *attr_desc;
attr_desc = find_attr_desc(attr_type);
if (!attr_desc || attr_desc->name==NULL)
return "???";
return attr_desc->name;
}
/**
* Get STUN standard reason phrase for the specified error code.
*/
PJ_DEF(pj_str_t) pj_stun_get_err_reason(int err_code)
{
#if 0
/* Find error using linear search */
unsigned i;
for (i=0; i<PJ_ARRAY_SIZE(stun_err_msg_map); ++i) {
if (stun_err_msg_map[i].err_code == err_code)
return pj_str((char*)stun_err_msg_map[i].err_msg);
}
return pj_str(NULL);
#else
/* Find error message using binary search */
int first = 0;
int n = PJ_ARRAY_SIZE(stun_err_msg_map);
while (n > 0) {
int half = n/2;
int mid = first + half;
if (stun_err_msg_map[mid].err_code < err_code) {
first = mid+1;
n -= (half+1);
} else if (stun_err_msg_map[mid].err_code > err_code) {
n = half;
} else {
first = mid;
break;
}
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -