pjsip configuration: Make transport TOS values consistent with endpoints

Transport TOS values were interpreted as DSCP values without being documented
as such. Endpoint TOS values (tos_audio/tos_video) behaved normally as TOS
values have historically. This patch makes the transport TOS values behave as
TOS values and makes all TOS values readable as string values (e.g. AF11).
In addition, alembic scripts have been updated to use the proper field types
for all TOS/COS values.

(issue ASTERISK-23235)
Reported by: George Joseph
Review: https://reviewboard.asterisk.org/r/3304/
........

Merged revisions 410028 from http://svn.asterisk.org/svn/asterisk/branches/12


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@410029 65c4cc65-6c06-0410-ace0-fbb531ad65f3
changes/97/197/1
Jonathan Rose 11 years ago
parent 3f730662f7
commit f0b8590c14

@ -27,6 +27,13 @@ PJSIP:
PJSIP contacts, this means that the schema has been updated to add a user_agent
column. An alembic revision has been added to facilitate this update.
Realtime Configuration:
- PJSIP endpoint columns 'tos_audio' and 'tos_video' have been changed from yes/no
enumerators to string values. 'cos_audio' and 'cos_video' have been changed from
yes/no enumerators to integer values. PJSIP transport column 'tos' has been
changed from a yes/no enumerator to a string value. 'cos' has been changed from
a yes/no enumerator to an integer value.
From 12.0.0 to 12.1.0:
* The sound_place_into_conference sound used in Confbridge is now deprecated
and is no longer functional since it has been broken since its inception

@ -0,0 +1,61 @@
"""Fix tos and cos field types
Revision ID: 4c573e7135bd
Revises: 21e526ad3040
Create Date: 2014-03-05 12:16:56.618630
"""
# revision identifiers, used by Alembic.
revision = '4c573e7135bd'
down_revision = '21e526ad3040'
from alembic import op
from alembic import context
import sqlalchemy as sa
from sqlalchemy.dialects.postgresql import ENUM
YESNO_NAME = 'yesno_values'
YESNO_VALUES = ['yes', 'no']
def upgrade():
op.alter_column('ps_endpoints', 'tos_audio',
type_=sa.String(10))
op.alter_column('ps_endpoints', 'tos_video',
type_=sa.String(10))
op.alter_column('ps_transports', 'tos',
type_=sa.String(10))
# Can't cast YENO_VALUES to Integers, so dropping and adding is required
op.drop_column('ps_endpoints', 'cos_audio')
op.drop_column('ps_endpoints', 'cos_video')
op.drop_column('ps_transports', 'cos')
op.add_column('ps_endpoints', sa.Column('cos_audio', sa.Integer))
op.add_column('ps_endpoints', sa.Column('cos_video', sa.Integer))
op.add_column('ps_transports', sa.Column('cos', sa.Integer))
pass
def downgrade():
yesno_values = ENUM(*YESNO_VALUES, name=YESNO_NAME, create_type=False)
# Can't cast string to YESNO_VALUES, so dropping and adding is required
op.drop_column('ps_endpoints', 'tos_audio')
op.drop_column('ps_endpoints', 'tos_video')
op.drop_column('ps_transports', 'tos')
op.add_column('ps_endpoints', sa.Column('tos_audio', yesno_values))
op.add_column('ps_endpoints', sa.Column('tos_video', yesno_values))
op.add_column('ps_transports', sa.Column('tos', yesno_values))
# Can't cast integers to YESNO_VALUES, so dropping and adding is required
op.drop_column('ps_endpoints', 'cos_audio')
op.drop_column('ps_endpoints', 'cos_video')
op.drop_column('ps_transports', 'cos')
op.add_column('ps_endpoints', sa.Column('cos_audio', yesno_values))
op.add_column('ps_endpoints', sa.Column('cos_video', yesno_values))
op.add_column('ps_transports', sa.Column('cos', yesno_values))
pass

@ -357,6 +357,17 @@ int ast_str2tos(const char *value, unsigned int *tos);
*/
const char *ast_tos2str(unsigned int tos);
/*!
* \brief Convert a TOS value into its string representation
* and create a dynamically allocated copy
*
* \param tos The TOS value to look up
* \param buf pointer to character pointer where string will be duplicated to
*
* \note The string allocated at buf must be free'd
*/
void ast_tos2str_buf(unsigned int tos, char **buf);
/*!
* \brief Retrieve a named ACL
*

@ -894,6 +894,12 @@ const char *ast_tos2str(unsigned int tos)
return "unknown";
}
void ast_tos2str_buf(unsigned int tos, char **buf)
{
const char *tos_string = ast_tos2str(tos);
*buf = ast_strdup(tos_string);
}
int ast_get_ip(struct ast_sockaddr *addr, const char *hostname)
{
return ast_get_ip_or_srv(addr, hostname, NULL);

@ -121,9 +121,11 @@ static void *transport_alloc(const char *name)
static void set_qos(struct ast_sip_transport *transport, pj_qos_params *qos)
{
int tos_as_dscp = transport->tos >> 2;
if (transport->tos) {
qos->flags |= PJ_QOS_PARAM_HAS_DSCP;
qos->dscp_val = transport->tos;
qos->dscp_val = tos_as_dscp;
}
if (transport->cos) {
qos->flags |= PJ_QOS_PARAM_HAS_SO_PRIO;
@ -448,6 +450,39 @@ static int localnet_to_str(const void *obj, const intptr_t *args, char **buf)
return 0;
}
/*! \brief Custom handler for TOS setting */
static int transport_tos_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
{
struct ast_sip_transport *transport = obj;
unsigned int value;
if (ast_str2tos(var->value, &value)) {
ast_log(LOG_ERROR, "Error configuring transport '%s' - Could not "
"interpret 'tos' value '%s'\n",
ast_sorcery_object_get_id(transport), var->value);
return -1;
}
if (value % 4) {
value = value >> 2;
value = value << 2;
ast_log(LOG_WARNING,
"transport '%s' - 'tos' value '%s' uses bits that are "
"discarded when converted to DSCP. Using equivalent %d instead.\n",
ast_sorcery_object_get_id(transport), var->value, value);
}
transport->tos = value;
return 0;
}
static int tos_to_str(const void *obj, const intptr_t *args, char **buf)
{
const struct ast_sip_transport *transport = obj;
ast_tos2str_buf(transport->tos, buf);
return 0;
}
static struct ao2_container *cli_get_container(void)
{
RAII_VAR(struct ao2_container *, container, NULL, ao2_cleanup);
@ -581,7 +616,7 @@ int ast_sip_initialize_sorcery_transport(void)
ast_sorcery_object_field_register_custom(sorcery, "transport", "method", "", transport_tls_method_handler, tls_method_to_str, 0, 0);
ast_sorcery_object_field_register_custom(sorcery, "transport", "cipher", "", transport_tls_cipher_handler, transport_tls_cipher_to_str, 0, 0);
ast_sorcery_object_field_register_custom(sorcery, "transport", "local_net", "", transport_localnet_handler, localnet_to_str, 0, 0);
ast_sorcery_object_field_register(sorcery, "transport", "tos", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_transport, tos));
ast_sorcery_object_field_register_custom(sorcery, "transport", "tos", "0", transport_tos_handler, tos_to_str, 0, 0);
ast_sorcery_object_field_register(sorcery, "transport", "cos", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_transport, cos));
ast_sip_register_endpoint_formatter(&endpoint_transport_formatter);

@ -758,6 +758,45 @@ static int t38udptl_ec_to_str(const void *obj, const intptr_t *args, char **buf)
return 0;
}
static int tos_handler(const struct aco_option *opt,
struct ast_variable *var, void *obj)
{
struct ast_sip_endpoint *endpoint = obj;
unsigned int value;
if (ast_str2tos(var->value, &value)) {
ast_log(LOG_ERROR, "Error configuring endpoint '%s' - Could not "
"interpret '%s' value '%s'\n",
ast_sorcery_object_get_id(endpoint), var->name, var->value);
return -1;
}
if (!strcmp(var->name, "tos_audio")) {
endpoint->media.tos_audio = value;
} else if (!strcmp(var->name, "tos_video")) {
endpoint->media.tos_video = value;
} else {
/* If we reach this point, someone called the tos_handler when they shouldn't have. */
ast_assert(0);
return -1;
}
return 0;
}
static int tos_audio_to_str(const void *obj, const intptr_t *args, char **buf)
{
const struct ast_sip_endpoint *endpoint = obj;
ast_tos2str_buf(endpoint->media.tos_audio, buf);
return 0;
}
static int tos_video_to_str(const void *obj, const intptr_t *args, char **buf)
{
const struct ast_sip_endpoint *endpoint = obj;
ast_tos2str_buf(endpoint->media.tos_video, buf);
return 0;
}
static int set_var_handler(const struct aco_option *opt,
struct ast_variable *var, void *obj)
{
@ -1586,8 +1625,8 @@ int ast_res_pjsip_initialize_configuration(const struct ast_module_info *ast_mod
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "allow_transfer", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, allowtransfer));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "sdp_owner", "-", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, media.sdpowner));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "sdp_session", "Asterisk", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, media.sdpsession));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "tos_audio", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, media.tos_audio));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "tos_video", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, media.tos_video));
ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "tos_audio", "0", tos_handler, tos_audio_to_str, 0, 0);
ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "tos_video", "0", tos_handler, tos_video_to_str, 0, 0);
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "cos_audio", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, media.cos_audio));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "cos_video", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, media.cos_video));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "allow_subscribe", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, subscription.allow));

Loading…
Cancel
Save